| Thread overview | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
December 30, 2010 [SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
As easily verified e.g. by compiling
---
extern(C) void foo() {}
pragma( msg, typeof( &foo ) );
---,
function pointers types include the linkage type (the code above prints »void C function()«).
However, there is no way to specify the linkage type e.g. in the signature of a function accepting a delegate, i.e.:
---
extern(C) void foo() {}
void bar( void function() func ) {} // How to correctly specify the full parameter type here?
void main() {
bar( &foo );
}
---
This problem is currently somewhat hidden by the fact that DMD simply ignores the linkage when doing type checking. But e.g. LDC does strict type checking (probably because it needs to reflect the pointer types in the LLVM IR, but that's just guessing) today, and it will hopefully be added to DMD at some point.
Note: Simply adding »extern( C )« to the type specification does not work, but: At the first glance, I couldn't even find any section in the language spec for both D1 and D2 mentioning linkage annotations for function pointers. Has this part simply not been spec'd yet?
In any case, this currently breaks passing of function pointers to C functions resp. their SWIG-generated wrappers with LDC, as I could find no easy way to work around it – creating an alias for the function pointer type before might work, as extern( C ) seems to be accepted there, but this is a major annoyance if you are automatically generating code.
David
| ||||
December 30, 2010 Re: [SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | Try this:
extern(C) void foo() {}
extern(C)
{
alias void function() FooFunc;
// alias typeof(foo) FooFunc; // or try this one if it works
}
void bar(FooFunc func) { }
void main() {
bar( &foo );
}
I've had a nasty bug where I forgot to put extern(C) on a function type like that. I spend the entire day trying to debug the damn thing, because for some reason calling C code worked, but C code trying to call a delegate which I've passed failed with arbitrary types. Basically, it was a communication mismatch with the calling convention.
On 12/30/10, David Nadlinger <see@klickverbot.at> wrote:
> As easily verified e.g. by compiling
> ---
> extern(C) void foo() {}
> pragma( msg, typeof( &foo ) );
> ---,
> function pointers types include the linkage type (the code above prints
> »void C function()«).
>
> However, there is no way to specify the linkage type e.g. in the signature of a function accepting a delegate, i.e.:
> ---
> extern(C) void foo() {}
> void bar( void function() func ) {} // How to correctly specify the full
> parameter type here?
>
> void main() {
> bar( &foo );
> }
> ---
>
> This problem is currently somewhat hidden by the fact that DMD simply ignores the linkage when doing type checking. But e.g. LDC does strict type checking (probably because it needs to reflect the pointer types in the LLVM IR, but that's just guessing) today, and it will hopefully be added to DMD at some point.
>
> Note: Simply adding »extern( C )« to the type specification does not work, but: At the first glance, I couldn't even find any section in the language spec for both D1 and D2 mentioning linkage annotations for function pointers. Has this part simply not been spec'd yet?
>
> In any case, this currently breaks passing of function pointers to C functions resp. their SWIG-generated wrappers with LDC, as I could find no easy way to work around it – creating an alias for the function pointer type before might work, as extern( C ) seems to be accepted there, but this is a major annoyance if you are automatically generating code.
>
>
> David
>
| |||
December 30, 2010 Re: [SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
I'm pretty sure this will work as well, because I have this defined in
a module where I'm passing a function pointer to C:
alias extern(C) size_t function(/*params*/) CallbackType;
Here's a snippet of how I used the OS to get a pointer to a C function, which I've used to pass my own callback, and get a struct back (or a pointer to one anyway):
alias extern(C) size_t function(AEffect* effect, int opcode, int
index, size_t value, void* ptr, float opt) audioMasterCallback;
extern(C) size_t HostCallback(AEffect* effect, int opcode, int index,
size_t value, void* ptr, float opt)
{
// code..
}
extern(C)
{
alias AEffect* function(audioMasterCallback) EntryProc;
}
EntryProc getMainEntry()
{
auto MainEntry = cast(EntryProc)GetProcAddress(VSTModule,
"VSTPluginMain");
// Older VSTs use "main" entry point
if (!MainEntry)
MainEntry = cast(EntryProc)GetProcAddress(VSTModule, "main");
if (MainEntry is null)
throw new Exception("Entry function 'VSTPluginMain' or 'main'
not found.");
return MainEntry;
}
AEffect* getEffect()
{
EntryProc VSTMain = getMainEntry();
auto effect = VSTMain(&HostCallback); // Passing the function address to C,
// and getting back a struct
if (effect is null)
throw new Exception("VST failed to return the effect struct.");
return effect;
}
It was code to load DLLs with a defined standard, all DLLs that conform to the spec need to have an entry point function with a specific name, and then I can pass a callback and in turn I get back this nice structure where I can figure things out the functionality of that "VST" plugin.
On 12/30/10, Andrej Mitrovic <andrej.mitrovich@gmail.com> wrote:
> Try this:
>
> extern(C) void foo() {}
> extern(C)
> {
> alias void function() FooFunc;
> // alias typeof(foo) FooFunc; // or try this one if it works
> }
>
> void bar(FooFunc func) { }
>
> void main() {
> bar( &foo );
> }
>
> I've had a nasty bug where I forgot to put extern(C) on a function type like that. I spend the entire day trying to debug the damn thing, because for some reason calling C code worked, but C code trying to call a delegate which I've passed failed with arbitrary types. Basically, it was a communication mismatch with the calling convention.
>
>
>
> On 12/30/10, David Nadlinger <see@klickverbot.at> wrote:
>> As easily verified e.g. by compiling
>> ---
>> extern(C) void foo() {}
>> pragma( msg, typeof( &foo ) );
>> ---,
>> function pointers types include the linkage type (the code above prints
>> »void C function()«).
>>
>> However, there is no way to specify the linkage type e.g. in the signature of a function accepting a delegate, i.e.:
>> ---
>> extern(C) void foo() {}
>> void bar( void function() func ) {} // How to correctly specify the full
>> parameter type here?
>>
>> void main() {
>> bar( &foo );
>> }
>> ---
>>
>> This problem is currently somewhat hidden by the fact that DMD simply ignores the linkage when doing type checking. But e.g. LDC does strict type checking (probably because it needs to reflect the pointer types in the LLVM IR, but that's just guessing) today, and it will hopefully be added to DMD at some point.
>>
>> Note: Simply adding »extern( C )« to the type specification does not work, but: At the first glance, I couldn't even find any section in the language spec for both D1 and D2 mentioning linkage annotations for function pointers. Has this part simply not been spec'd yet?
>>
>> In any case, this currently breaks passing of function pointers to C functions resp. their SWIG-generated wrappers with LDC, as I could find no easy way to work around it – creating an alias for the function pointer type before might work, as extern( C ) seems to be accepted there, but this is a major annoyance if you are automatically generating code.
>>
>>
>> David
>>
>
| ||||
December 30, 2010 Re: [SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 12/30/10 10:44 PM, Andrej Mitrovic wrote:
> Try this: [snip]
Thanks for your answer, but as I mentioned in my original post, I don't see why creating an alias for the function pointer type should be necessary – it is quite annoying when you are automatically creating code, you'd need a special case for function pointers then.
David
| |||
December 30, 2010 Re: [SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to David Nadlinger | Yes, I agree. This will not work either but I'd like it to:
extern(C) void foo() { }
void bar(typeof(foo) func) { }
> Error: variable main.bar.func cannot be declared to be a function
Try filing a feature request on bugzilla.
On 12/30/10, David Nadlinger <see@klickverbot.at> wrote:
> On 12/30/10 10:44 PM, Andrej Mitrovic wrote:
>> Try this: [snip]
>
> Thanks for your answer, but as I mentioned in my original post, I don't see why creating an alias for the function pointer type should be necessary – it is quite annoying when you are automatically creating code, you'd need a special case for function pointers then.
>
> David
>
| |||
December 30, 2010 Spec Bug (?): calling convention of function pointers (D1 and D2) | ||||
|---|---|---|---|---|
| ||||
Posted in reply to Andrej Mitrovic | On 12/30/10 11:29 PM, Andrej Mitrovic wrote:
> Try filing a feature request on bugzilla.
I don't quite see how this would be a feature request – »I'd like to be able to actually express the implicitly used types in D code«?
The reason I brought this here instead of directly filing a specification bug to Bugzilla is that 1) I am not sure if I had missed a related part of the specification and 2) since resolving this issue will probably require a change/addition to the language specification, I think it deserves some extended discussion.
So, to restate the question: Currently, the spec for both D1 and D2 apparently does not allow specifying the calling convention of function pointer types directly. This issue probably hasn't popped up so far just becasue DMD currently does not take the calling convention into account when type-checking function pointers, but this might not be the case for other compilers or future versions of DMD. How should we resolve this issue?
David
| |||
Copyright © 1999-2021 by the D Language Foundation
Permalink
Reply