[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