Please do not reply to this email- if you want to comment on the bug, go to the URL shown below and enter your comments there.
Changed by [EMAIL PROTECTED] http://bugzilla.ximian.com/show_bug.cgi?id=79312 --- shadow/79312 2006-09-07 17:04:09.000000000 -0400 +++ shadow/79312.tmp.20786 2006-09-07 18:08:48.000000000 -0400 @@ -176,6 +176,192 @@ ------- Additional Comments From [EMAIL PROTECTED] 2006-09-07 17:04 ------- Jim, if you still have questions, reopen the bug. + +------- Additional Comments From [EMAIL PROTECTED] 2006-09-07 18:08 ------- +Apologies for dragging this out. I agree w/ your assessment (for the +most part +:) ). It's a C-linkage question more than anything to do w/ Mono. +Short answer +is that per PPC32 OSX ABI standards, void* are returned in GPR3, whereas +composite values are returned as an address in GPR3. I'm including the +code I +used to demonstrate this to myself. + +I still have 2 questions. + +1. Since "IntPtr" is defined as struct, why doesn't it fall to the +same incorrect +bindings as any other struct? Is it a special-case at the p/invoke code? + +2. Can I use a MarshalAs attribute to force the proper return value +semantics? +I've tried this but could not get desired behavior. + +Many thanks! +Jim + +--- Apple's PPC32 ABI ---- + +http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/LowLevelABI.pdf + +32-bit PowerPC Function Calling Conventions + +* Returning Results * +The following list describes where a function's return value is passed +to the caller. + +- Scalars smaller than 4 bytes (such as char and short) are placed in +the low + word of GPR3. The register's highword is undefined. + +- Scalars 4 bytes in size (such as long, int, and pointers, including +array + pointers) are placed in GPR3. + +- Values of type long long are returned in the high word of GPR3 and +the low + word of GPR4. + +- Floating-point values are placed in FPR1. + +- Composite values (such as struct and union) and values larger than 4 +bytes + are placed at the location pointed to by GPR3. + +--- Apple's PPC32 ABI (End) ---- + +--- The gory details ---- + +$ cat pt.c + +struct ShortPoint { + short x; + short y; +}; + +struct ShortPoint GetPoint() { + struct ShortPoint ret = { 16, 32 }; + return ret; +} + +void* GetPVoid() { + return (void*)8192; +} + +$ gcc -c pt.c +$ gcc -dynamiclib -o pt.dylib pt.o + +$ cat callpt.cs + +using System; +using System.Runtime.InteropServices; + +struct ShortPoint { + internal short x; + internal short y; +} + +struct IntStruct { + internal int x; +} + +struct Call { + const string LIB = "pt.dylib"; + + public static void Main() { + ShortPoint pt = GetPoint(); + Console.WriteLine("x: {0} y: {1}", (int)pt.x, (int)pt.y); + + IntPtr a = GetPVoid1(); + IntStruct b = GetPVoid2(); + Console.WriteLine("a: {0} b: {1}", (int)a, (int)b.x); + } + + [DllImport(LIB)] + public static extern ShortPoint GetPoint(); + + [DllImport(LIB, EntryPoint="GetPVoid")] + public static extern IntPtr GetPVoid1(); + + [DllImport(LIB, EntryPoint="GetPVoid")] + public static extern IntStruct GetPVoid2(); + +} + +$ mcs -warn:4 callpt.cs +$ mono callpt.exe +x: 16 y: 32 +a: 8192 b: 0 + +$ cat callpt.c + +#include <dlfcn.h> +#include <stdio.h> + +struct ShortPoint { + short x; + short y; +}; + +typedef struct ShortPoint (*GETPT)(); +typedef void* (*GETPV)(); + +int main(int argc, char* argv[]) { + void* lib = dlopen("pt.dylib", RTLD_LAZY); + if (lib == 0) { + return 1; + } + GETPT GetPoint = (GETPT)dlsym(lib, "GetPoint"); + GETPV GetPVoid = (GETPV)dlsym(lib, "GetPVoid"); + struct ShortPoint pt = GetPoint(); + void* pv = GetPVoid(); + printf("x: %hd, y: %hd\n", pt.x, pt.y); + printf("p: %d\n", pv); + dlclose(lib); + return 0; +} + +$ gcc -g -o callpt callpt.c +$ gcc -g -c pt.c +$ gcc -dynamiclib -o pt.dylib pt.o + +$ ./callpt +x: 16, y: 32 +p: 8192 + +$ gdb callpt + +(gdb) disas +Dump of assembler code for function GetPoint: +0x00006f44 <GetPoint+0>: stmw r30,-8(r1) +0x00006f48 <GetPoint+4>: stwu r1,-64(r1) +0x00006f4c <GetPoint+8>: mr r30,r1 +0x00006f50 <GetPoint+12>: mr r2,r3 +0x00006f54 <GetPoint+16>: li r0,16 +0x00006f58 <GetPoint+20>: sth r0,24(r30) +0x00006f5c <GetPoint+24>: li r0,32 +0x00006f60 <GetPoint+28>: sth r0,26(r30) +0x00006f64 <GetPoint+32>: lwz r0,24(r30) +0x00006f68 <GetPoint+36>: stw r0,0(r2) +0x00006f6c <GetPoint+40>: mr r3,r2 ; <-- return ref to +stack in r3 +0x00006f70 <GetPoint+44>: lwz r1,0(r1) +0x00006f74 <GetPoint+48>: lmw r30,-8(r1) +0x00006f78 <GetPoint+52>: blr +End of assembler dump. + +(gdb) disas +Dump of assembler code for function GetPVoid: +0x00006f7c <GetPVoid+0>: stmw r30,-8(r1) +0x00006f80 <GetPVoid+4>: stwu r1,-48(r1) +0x00006f84 <GetPVoid+8>: mr r30,r1 +0x00006f88 <GetPVoid+12>: li r0,8192 +0x00006f8c <GetPVoid+16>: mr r3,r0 ; <-- return value in r3 +0x00006f90 <GetPVoid+20>: lwz r1,0(r1) +0x00006f94 <GetPVoid+24>: lmw r30,-8(r1) +0x00006f98 <GetPVoid+28>: blr +End of assembler dump. + _______________________________________________ mono-bugs maillist - [email protected] http://lists.ximian.com/mailman/listinfo/mono-bugs
