Thread overview
My is the order of parameters reversed for functions that are dynamically loaded from shared C libraries?
Nov 15, 2015
David Nies
Nov 15, 2015
David Nadlinger
Nov 15, 2015
David Nies
Nov 15, 2015
Andrea Fontana
Nov 15, 2015
David Nadlinger
Nov 15, 2015
David Nies
November 15, 2015
Apparantly, the order in which parameters are passed to a dynamically loaded C function is reversed. See the following minimal example:

----------------
%> cat dll.c
#include "stdio.h"

int dll2(const char* first, const char* second) {
    printf("dll2() - first: '%s', second: '%s'\n", first, second);
    return 0;
}

int dll3(const char* first, const char* second, const char* third) {
    printf("dll3() - first: '%s', second: '%s', third: '%s'\n",
           first,
           second,
           third);
    return 0;
}
----------------

I compiled it with the following commands:

%> gcc -c dll.c -fpic
%> gcc -shared -o libdll.dyld dll.o
%> file libdll.dyld
libdll.dyld: Mach-O 64-bit dynamically linked shared library x86_64

Now, I'm using it with a very simple D program and see very unexpected results:

----------------
%> cat main.d
import std.stdio, std.string, core.sys.posix.dlfcn;

// extern functions
alias nothrow int function(const char*, const char*) dll2_fn;
alias nothrow int function(const char*, const char*, const char*) dll3_fn;

void main() {
    string sdlLibPath = "libdll.dyld";
    auto libraryHandle = dlopen(sdlLibPath.toStringz(), RTLD_LAZY);
    scope(exit) dlclose(libraryHandle);

    dll2_fn dll2 = cast(dll2_fn)dlsym(libraryHandle, "dll2");
    dll2("one", "two");

    dll3_fn dll3 = cast(dll3_fn)dlsym(libraryHandle, "dll3");
    dll3("one", "two", "three");
}

%> rdmd main.d
dll2() - first: 'two', second: 'one'
dll3() - first: 'three', second: 'two', third: 'one'
----------------

The order in which the C functions get the parameters is exactly the reverse order in which I supply them in D.

What is happening there? I also tried to export a function that has two different types from the C library. Calling it the same way from the client D program causes a segfault - which I'd expect when the parameters are really reversed.

How can I make sure the order is correct?
November 15, 2015
On Sunday, 15 November 2015 at 17:54:27 UTC, David Nies wrote:
> How can I make sure the order is correct?

Whenever you use a C function, it must be marked as, even if it's through a function pointer as in this case. Just apply the attribute to the dll2_fn and dll3_fn declarations.

Hope this helps,
David
November 15, 2015
On Sunday, 15 November 2015 at 18:00:09 UTC, David Nadlinger wrote:
> On Sunday, 15 November 2015 at 17:54:27 UTC, David Nies wrote:
>> How can I make sure the order is correct?
>
> Whenever you use a C function, it must be marked as, even if it's through a function pointer as in this case. Just apply the attribute to the dll2_fn and dll3_fn declarations.
>
> Hope this helps,
> David

How do I mark it as such? Can you please give an example?

Thanks for the quick reply! :)
November 15, 2015
On Sunday, 15 November 2015 at 18:02:01 UTC, David Nies wrote:
> On Sunday, 15 November 2015 at 18:00:09 UTC, David Nadlinger wrote:
>> On Sunday, 15 November 2015 at 17:54:27 UTC, David Nies wrote:
>>> How can I make sure the order is correct?
>>
>> Whenever you use a C function, it must be marked as, even if it's through a function pointer as in this case. Just apply the attribute to the dll2_fn and dll3_fn declarations.
>>
>> Hope this helps,
>> David
>
> How do I mark it as such? Can you please give an example?
>
> Thanks for the quick reply! :)

I think he refers to this: http://dlang.org/interfaceToC.html
November 15, 2015
On Sunday, 15 November 2015 at 18:02:01 UTC, David Nies wrote:
> How do I mark it as such? Can you please give an example?
>
> Thanks for the quick reply! :)

Just add extern(C) to the beginning of the "alias" line.

 — David
November 15, 2015
On Sunday, 15 November 2015 at 18:12:52 UTC, David Nadlinger wrote:
> On Sunday, 15 November 2015 at 18:02:01 UTC, David Nies wrote:
>> How do I mark it as such? Can you please give an example?
>>
>> Thanks for the quick reply! :)
>
> Just add extern(C) to the beginning of the "alias" line.
>
>  — David

Great! Thanks to all of you! That was really quick and helpful!