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?