Thread overview |
---|
November 02, 2019 Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Hello, When trying to pass a D function to the C callback, the compiler says: 'Error: cannot implicitly convert expression &this.onProcessCb of type extern (C) bool delegate(const(short*) a, ulong b, void* c) to extern (C) bool function(const(short*), ulong, void*' because my function is member of a class (compiles when the function is out of the class). Is there any way to say to solve this ? The wiki isn't very clear about the C callbacks: https://dlang.org/spec/interfaceToC.html#callbacks C code: ---- typedef bool (*onProcessCallback)(const short*, size_t, void*); ---- D Code: ----- class Game { onProcessCallback m_onProcessCb; this() { m_onProcessCb = &onProcessCb; // Error here } void onProcess() { // ... } extern(C) bool onProcessCb(const short* a, size_t b, void* c) { onProcess(); return true; } } private extern(C) { // Should call onProcess() when executed by the C lib alias onProcessCallback = bool function(const short*, size_t, void*); } ----- |
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luh | On Saturday, 2 November 2019 at 17:49:09 UTC, Luh wrote:
> Hello,
>
> When trying to pass a D function to the C callback, the compiler says:
>
> 'Error: cannot implicitly convert expression &this.onProcessCb of type extern (C) bool delegate(const(short*) a, ulong b, void* c) to extern (C) bool function(const(short*), ulong, void*'
>
> because my function is member of a class (compiles when the function is out of the class).
>
> Is there any way to say to solve this ?
> The wiki isn't very clear about the C callbacks:
> https://dlang.org/spec/interfaceToC.html#callbacks
>
> C code:
> ----
> typedef bool (*onProcessCallback)(const short*, size_t, void*);
> ----
>
>
> D Code:
> -----
> class Game
> {
> onProcessCallback m_onProcessCb;
>
> this()
> {
> m_onProcessCb = &onProcessCb; // Error here
> }
>
> void onProcess()
> {
> // ...
> }
>
> extern(C) bool onProcessCb(const short* a, size_t b, void* c)
> {
> onProcess();
> return true;
> }
> }
>
> private extern(C)
> {
> // Should call onProcess() when executed by the C lib
> alias onProcessCallback = bool function(const short*, size_t, void*);
> }
> -----
you are missing a static in your member function's signature.
The callback is not providing a this pointer.
|
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luh | On Saturday, 2 November 2019 at 17:49:09 UTC, Luh wrote: > Hello, > > When trying to pass a D function to the C callback, the compiler says: > > 'Error: cannot implicitly convert expression &this.onProcessCb of type extern (C) bool delegate(const(short*) a, ulong b, void* c) to extern (C) bool function(const(short*), ulong, void*' > > because my function is member of a class (compiles when the function is out of the class). > > Is there any way to say to solve this ? > The wiki isn't very clear about the C callbacks: > https://dlang.org/spec/interfaceToC.html#callbacks > > C code: > ---- > typedef bool (*onProcessCallback)(const short*, size_t, void*); > ---- > > > D Code: > ----- > class Game > { > onProcessCallback m_onProcessCb; > > this() > { > m_onProcessCb = &onProcessCb; // Error here > } > > void onProcess() > { > // ... > } > > extern(C) bool onProcessCb(const short* a, size_t b, void* c) > { > onProcess(); > return true; > } > } > > private extern(C) > { > // Should call onProcess() when executed by the C lib > alias onProcessCallback = bool function(const short*, size_t, void*); > } > ----- This is because onProcessCb is a member of an object. Therefore, it carries also the information about the context, which includes e.g. all members of the class. Due to this onProcessCb is a delegate, which is something different from a function, cf. https://dlang.org/spec/function.html#closures So, there is a type mismatch. |
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stefan Koch | On Saturday, 2 November 2019 at 18:31:28 UTC, Stefan Koch wrote:
> On Saturday, 2 November 2019 at 17:49:09 UTC, Luh wrote:
>> Hello,
>>
>> When trying to pass a D function to the C callback, the compiler says:
>>
>> 'Error: cannot implicitly convert expression &this.onProcessCb of type extern (C) bool delegate(const(short*) a, ulong b, void* c) to extern (C) bool function(const(short*), ulong, void*'
>>
>> because my function is member of a class (compiles when the function is out of the class).
>>
>> Is there any way to say to solve this ?
>> The wiki isn't very clear about the C callbacks:
>> https://dlang.org/spec/interfaceToC.html#callbacks
>>
>> C code:
>> ----
>> typedef bool (*onProcessCallback)(const short*, size_t, void*);
>> ----
>>
>>
>> D Code:
>> -----
>> class Game
>> {
>> onProcessCallback m_onProcessCb;
>>
>> this()
>> {
>> m_onProcessCb = &onProcessCb; // Error here
>> }
>>
>> void onProcess()
>> {
>> // ...
>> }
>>
>> extern(C) bool onProcessCb(const short* a, size_t b, void* c)
>> {
>> onProcess();
>> return true;
>> }
>> }
>>
>> private extern(C)
>> {
>> // Should call onProcess() when executed by the C lib
>> alias onProcessCallback = bool function(const short*, size_t, void*);
>> }
>> -----
>
> you are missing a static in your member function's signature.
> The callback is not providing a this pointer.
My problem is, that the onProcess function should not be static because it uses a variable inside the class.
like:
-----
class Game
{
private short[] m_a;
void onProcess(short[] a)
{
m_a ~= a;
// ...
}
extern(C) bool onProcessCb(const short* a, size_t b, void* c)
{
onProcess();
return true;
}
}
-----
So I think I just can't. :(
|
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luh | On Saturday, 2 November 2019 at 19:42:54 UTC, Luh wrote:
> So I think I just can't. :(
Is that `void* c` in the callback a context pointer by any chance?
That's a common thing in C callbacks precisely for purposes like this.
You can cast your class to a void* when you register the callback and in the callback function cast it back to a class and call process on that.
I don't know what C library you're working with so can't give you specifics.
|
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dennis | On Saturday, 2 November 2019 at 19:55:58 UTC, Dennis wrote:
> On Saturday, 2 November 2019 at 19:42:54 UTC, Luh wrote:
>> So I think I just can't. :(
>
> Is that `void* c` in the callback a context pointer by any chance?
> That's a common thing in C callbacks precisely for purposes like this.
> You can cast your class to a void* when you register the callback and in the callback function cast it back to a class and call process on that.
>
> I don't know what C library you're working with so can't give you specifics.
Yup that's it !
Many thanks !
|
November 02, 2019 Re: Unable to pass a D function member to a C callback | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luh | On Saturday, 2 November 2019 at 20:42:29 UTC, Luh wrote: > Yup that's it ! > Many thanks ! One word of warning: ensure the C library does not have the only reference to your Game class instance, or the garbage collector might deallocate it since it does not scan threads created by C libraries. See: https://dlang.org/spec/garbage.html#gc_foreign_obj |
Copyright © 1999-2021 by the D Language Foundation