OK, I've been investigating (couldn't wait), heres what I've got so far: Recap: Using GetProcAddress to get a pointer (p_ldiv)to CRTDLL's "ldiv" function, and calling through that pointer produces errors in some cases. This is because ldiv returns a struct. The problem occurs for any dll function that returns a struct when one side (the process or the dll) is not the same as the other. There are four situations to consider: 1. unix application calls unix .so 2. unix application calls win32 .dll 3. win32 application calls unix .so 4. win32 application calls win32 .dll Case 1. unix calls unix (winelib apps) This works fine. function pointer is defined as: ldiv_t (__cdecl *p_ldiv)() = 0; and the returned struct is assigned without problem: ldiv_t ldt = p_ldiv(20L,3L); Case 2. unix calls win32 (winelib, wine) Doesn't work using the above code. ldiv_t is filled with crap. The following works however: void (__cdecl *p_ldiv2)() = 0; /* Note void return! */ ldiv_t ldt; p_ldiv2(20L,3L); __asm__ __volatile__( "movl %%eax, %0;" : "=m" (ldt.quot) : ); __asm__ __volatile__( "movl %%edx, %0;" : "=m" (ldt.rem) : ); Because in this case VC returns structs < 8 bytes in registers. Note that this code will crash in case 1 (i.e. if unix .so is called). Case 3. win32 calls unix (wine) Crashes into debugger (see last post for trace). I can fix this by modifying the .so, so the .spec calls my function: @ cdecl ldiv(long long) CRTDLL_ldiv which I implement as: void __cdecl CRTDLL_ldiv(long x, long y) { ldiv_t ldt = ldiv(x,y); __asm__ __volatile__( "movl %0, %%eax;" : "=m" (ldt.quot) : ); __asm__ __volatile__( "movl %0, %%edx;" : "=m" (ldt.rem) : ); } i.e. I load the struct into registers before returning. Of course, this wont work with a unix caller. Case 4. win32 calls win32 (wine) This works fine, as you'd expect. The pointer and call are exactly as in case 1. Summary/Suggestions: struct return conventions are different between gcc on linux and win32 (and probably solaris etc as well). The method of gcc's returns hasn't been investigated, but we cant change it anyway, unless we want the Wine installation to require a recompile of every binary on the box (including kernel), i.e *no way*. The problem is that we must dynamically decide how to return structs from .so based dlls based on whether the calling process is a native or win32 binary. I'll start the ball rolling with 3 suggested solutions: 1. Allow .spec files to specify struct return values. (I am not convinced this is a good idea anymore). .spec files could be enhanced as per my previous mail. The generated .spec.c file could hold a table of extra info about structs being returned and generate two stubs, one for host o/s calling programs, one for win32. The win32 stub would call the native version, load the returned value into registers, and return. winelib progs would just link direct to the native stub. GetProcAddress would determine the callers type and return the appropriate stub. Alternately, the base function could return its values in registers, and a stub would be generated for native calls. Theres a few possibilities around this area. PROS: DLLs dont have to know about the mechanism. CONS: Lots of work/overhead for a rarely used feature. More work to implement structs > 8 bytes. 2. Make the DLL's do it. Do something like: .h : #if defined(__GNUC__) && defined(__i386__) void __cdecl CRTDLL_ldiv(long x, long y) #else ldiv_t __cdecl CRTDLL_ldiv(long x, long y) #endif .c: #if defined(__GNUC__) && defined(__i386__) void __cdecl CRTDLL_ldiv(long x, long y) { ldiv_t ldt = ldiv(x,y); if (win32_caller()) { __asm__ __volatile__( "movl %0, %%eax;" : "=m" (ldt.quot) : ); __asm__ __volatile__( "movl %0, %%edx;" : "=m" (ldt.rem) : return; } _some_asm_here_to_push_the_return_value_the_way_gcc_does_ ); #else /* All other callers/platforms must be native (winelib) */ ldiv_t __cdecl CRTDLL_ldiv(long x, long y) { return ldiv(x,y); } #endif PROS: Dont have to touch spec files for this rare occurence Can handle returning structs > 8 bytes when (if) they come up. CONS: Must expose internal call to get process type for linux/x86 dlls Note: I have to make sure this works! 3. Add a new function attribute to gcc No Thanks. This would take forever... So there you have it. If someone knows how to determine whether the current process is native or win32, please let me know so I can test #2 out. Other than that, feedback please!! Cheers, Jon ===== "May their negative actions ripen upon me. And may all my virtues ripen upon them."-Nagarjuna, on Compassion "If it could be talked about, everybody would have told their brother."-Chuang Tzu, on Tao [EMAIL PROTECTED] , [EMAIL PROTECTED] __________________________________________________ Do You Yahoo!? Yahoo! Shopping - Thousands of Stores. Millions of Products. http://shopping.yahoo.com/