[SPEC/DMD] Bug (?): extern( C ) function pointers (D1 and D2)
Andrej Mitrovic
andrej.mitrovich at gmail.com
Thu Dec 30 13:53:55 PST 2010
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 at 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 at 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
>>
>
More information about the Digitalmars-d
mailing list