|
View:
New views
6 Messages
—
Rating Filter:
Alert me
|
|
|
Marshaling on MacI am calling a Carbon MAC OS X API function using p/invoke :
[DllImport("/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon", CharSet = CharSet.Ansi)] internal static extern int FSGetVolumeInfo( short volume, uint volumeIndex, ref short actualVolume, uint whichInfo, ref FSVolumeInfo info, ref HFSUniStr255 volumeName, ref FSRef rootDirectory); while the actual C prototype is : OSErr FSGetVolumeInfo ( FSVolumeRefNum volume, ItemCount volumeIndex, FSVolumeRefNum *actualVolume, FSVolumeInfoBitmap whichInfo, FSVolumeInfo *info, HFSUniStr255 *volumeName, FSRef *rootDirectory ); I'm mostly interested in the info ref parameter, which is of type FSVolumeInfo*. Here are the struct defs in C , and following are my C# marshaling targets : C : struct FSVolumeInfo { UTCDateTime createDate; UTCDateTime modifyDate; UTCDateTime backupDate; UTCDateTime checkedDate; UInt32 fileCount; UInt32 folderCount; UInt64 totalBytes; UInt64 freeBytes; UInt32 blockSize; UInt32 totalBlocks; UInt32 freeBlocks; UInt32 nextAllocation; UInt32 rsrcClumpSize; UInt32 dataClumpSize; UInt32 nextCatalogID; UInt8 finderInfo[32]; UInt16 flags; UInt16 filesystemID; UInt16 signature; UInt16 driveNumber; short driverRefNum; }; struct UTCDateTime { UInt16 highSeconds; UInt32 lowSeconds; UInt16 fraction; }; C# : [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] struct FSVolumeInfo { public UTCDateTime createDate; public UTCDateTime modifyDate; public UTCDateTime backupDate; public UTCDateTime checkedDate; public UInt32 fileCount; public UInt32 folderCount; public UInt64 totalBytes; public UInt64 freeBytes; public UInt32 blockSize; public UInt32 totalBlocks; public UInt32 freeBlocks; public UInt32 nextAllocation; public UInt32 rsrcClumpSize; public UInt32 dataClumpSize; public UInt32 nextCatalogID; [MarshalAs(UnmanagedType.ByValArray, SizeConst=32)] public byte[] finderInfo; public UInt16 flags; public UInt16 filesystemID; public UInt16 signature; public UInt16 driveNumber; public Int16 driverRefNum; }; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] struct UTCDateTime { public UInt16 highSeconds; public UInt32 lowSeconds; public UInt16 fraction; }; The invoking code looks something like this : //other variable initialization... FSVolumeInfo volInfo = new FSVolumeInfo(); int status = FSGetVolumeInfo(...ref volInfo.../*and some more params....*/); //...some more code //...print results in volInfo ... I'm getting back garbage in volInfo. I've compares the results of invoking this method via Mono (managed code) and the results when writing a native app in C which calls the same API method. It seems like the entire FSVolumeInfo struct I'm getting back using Mono is garbage.... The values are all wrong and marshaling seems not to work. I tried changing the UTCDateTime struct in c# to use explicit layout, as shown in the following : [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi)] struct UTCDateTime { [FieldOffset(0)] public UInt16 highSeconds; [FieldOffset(2)] public UInt32 lowSeconds; [FieldOffset(6)] public UInt16 fraction; }; And this makes all the values in the FSVolumeInfo instance up until "byte[] finderInfo;" look OK, but the rest of the fields after that are garbage again. *** Question number 1 : Why do I have to explicitly tell it the struct layout, it is pretty obviouse here isn't it ? shouldn't this just be simple blitting ? is it because of the fact that this is a struct being used under another struct ? Moving on ...The only thing I could do to make it work is kind of "give up" on the automatic marshaling of the array, and instead of "byte[] finderInfo;" replace it with a manually-declared-size struct, which now looks something like this : [StructLayout(LayoutKind.Sequential, Size = 32)] struct FinderInfoArrData { int values; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] struct FSVolumeInfo { //... same as before public FinderInfoArrData finderInfo; // ... the rest is same as before, and now the values here are OK too... } Changing the entire FSVolumeInfo to be Explicitly defined with [FieldOffset] (in addition to UTCDateTime being explicit) also works. It seems too error-prone to me and I'm trying to avoid it. My questions are : 1. Is it a mono issue that the simple struct-withing-struct scenario isn't blitted well ? or am I missing something while working against the Carbon libraries in terms of encoding/memory layout... 2. If it is, any knowledge of an open bug/fix planned in following release ? 3. Is it a mono issue that I have to either do fancy tricks and give up on auto-marshaling of the array in the middle, or set the Entire FSVolumeInfo struct layout to Explicit ? 4. [same as 2] Thanks, Yoni.S. |
|
|
Re: Marshaling on Macsilver83 wrote:
> *** Question number 1 : Why do I have to explicitly tell it the struct > layout, it is pretty obviouse here isn't it ? shouldn't this just be simple > blitting ? is it because of the fact that this is a struct being used under > another struct ? No. It's because UTCDateTime is defined within a `#pragma options align=mac68k' section in its C header file. This means it doesn't have a default structure packing. IIRC, "mac68k" packing means a packing of one, so your managed UTCDateTime struct must be declared with: [StructLayout(LayoutKind.Sequential, Pack = 1)] > My questions are : > 1. Is it a mono issue that the simple struct-withing-struct scenario isn't > blitted well ? or am I missing something while working against the Carbon > libraries in terms of encoding/memory layout... See above. > 3. Is it a mono issue that I have to either do fancy tricks and give up on > auto-marshaling of the array in the middle, or set the Entire FSVolumeInfo > struct layout to Explicit ? Check and adjust the packing of all other structs you're planning to use. It should fly then. Robert _______________________________________________ Mono-list maillist - Mono-list@... http://lists.ximian.com/mailman/listinfo/mono-list |
|
|
Re: Marshaling on MacSeems like you nailed it on the head, thanks a million !
Small follow ups : 1. Is this the case for all / most of Carbon APIs ? 2. Is there a concentrated reference to find out the Packing value per "#pragma options align" setting ? tried to google around to find out without much luck...
|
|
|
Re: Marshaling on MacAm 26.08.2008 um 10:19 schrieb silver83: > 1. Is this the case for all / most of Carbon APIs ? Mac68K seems to apply to ppc only, so no. To find out where it's necessary, check the header files on your system. > 2. Is there a concentrated reference to find out the Packing value per > "#pragma options > align" setting ? See the architecture-specific ABI documentation: http://developer.apple.com/documentation/DeveloperTools/Conceptual/LowLevelABI/Articles/32bitPowerPC.html#/ /apple_ref/doc/uid/TP40002438-DontLinkElementID_1 Andreas > Robert Jordan wrote: >> >> No. It's because UTCDateTime is defined within a `#pragma options >> align=mac68k' section in its C header file. >> >> This means it doesn't have a default structure packing. IIRC, >> "mac68k" packing means a packing of one, so your managed UTCDateTime >> struct must be declared with: >> >> [StructLayout(LayoutKind.Sequential, Pack = 1)] >> >> Robert _______________________________________________ Mono-list maillist - Mono-list@... http://lists.ximian.com/mailman/listinfo/mono-list |
|
|
Re: Marshaling on MacHi Andreas,
Andreas Färber wrote: > Am 26.08.2008 um 10:19 schrieb silver83: > >> 1. Is this the case for all / most of Carbon APIs ? > > Mac68K seems to apply to ppc only, so no. To find out where it's > necessary, check the header files on your system. It actually applies to all architectures. It means "use the same packing as we used a decade ago on a Mac68K under Mac OS 9". All Carbon headers exhibit this pragma. Robert _______________________________________________ Mono-list maillist - Mono-list@... http://lists.ximian.com/mailman/listinfo/mono-list |
|
|
Re: Marshaling on MacHi,
Am 27.08.2008 um 16:07 schrieb Robert Jordan: > Andreas Färber wrote: >> Am 26.08.2008 um 10:19 schrieb silver83: >> >>> 1. Is this the case for all / most of Carbon APIs ? >> >> Mac68K seems to apply to ppc only, so no. To find out where it's >> necessary, check the header files on your system. > > It actually applies to all architectures. > > It means "use the same packing as we used a decade ago on a Mac68K > under Mac OS 9". All Carbon headers exhibit this pragma. Hm, in the ABI docs its alignment rules are only listed for ppc, not ppc64 or IA-32... Mac68K differs from Packed encoding there, so Pack=1 would not seem to be the ultimate solution in all cases. Pack=2 might work better, except for vector (16), not sure how char (1) fits into this. In the worst case a custom helper for mashalling IntPtr <-> struct via Mac68K might need to be implemented? Andreas _______________________________________________ Mono-list maillist - Mono-list@... http://lists.ximian.com/mailman/listinfo/mono-list |
| Free Forum Powered by Nabble | Forum Help |