Passing C # string to an unmanaged C DLL in Windows Mobile

I have an unmanaged C ++ DLL that I need to call from a Windows Mobile C # application.

I have a C # shell and it works fine on the desktop. I can call DLL functions from a C # desktop program and pass strings without problems.

However, when I compile the lib and the wrapper for the mobile platform, I get an error message in the DllImport lines saying that CharSet.ANSI is not recognized. The only parameters that I am allowed to write are CharSet.Auto and CharSet.Unicode.

The problem is that regardless of this parameter, the strings received in C ++ functions are wide char strings, and not the regular char * strings they expect.

We can use wcstombs () to translate all the lines at the beginning of each C ++ function, but I would prefer not to modify lib to such an extent ...

Is there a way to fix marshalling between C # and C that works with the .NET Compact Framework?

+7
c ++ c # interop windows-mobile compact-framework
source share
3 answers

No no.

Microsoft documentation indicates that:

[...]. NET Compact Framework supports only Unicode and, therefore, includes only CharSet.Unicode (and CharSet.Auto which is equal to Unicode), and does not support any of the provisions of the Declare approval. This means that the ExactSpelling property is also not supported.

As a result, if your DLL function expects an ANSI string, you will need to convert to a DLL, or convert the string to an array of bytes using the overloaded GetBytes method of the ASCIIEncoding class , before calling the function, since the .NET Compact Framework will always have a pointer to the Unicode string. [...]

Decision:

DLL Functions

int MARSHALMOBILEDLL_API testString(const char* value); const char* MARSHALMOBILEDLL_API testReturnString(const char* value); 

Packing

 [DllImport("marshalMobileDll.dll")] public static extern int testString(byte[] value); [DllImport("marshalMobileDll.dll")] public static extern System.IntPtr testReturnString(byte[] value); 

Call code

 string s1 = "1234567"; int v = Wrapper.testString( Encoding.ASCII.GetBytes(s1)); string s2 = "abcdef"; IntPtr ps3 = Wrapper.testReturnString(Encoding.ASCII.GetBytes(s2)); string s3 = IntPtrToString(ps3); private string IntPtrToString(IntPtr intPtr) { string retVal = ""; byte b = 0; int i = 0; while ((b = Marshal.ReadByte(intPtr, i++)) != 0) { retVal += Convert.ToChar(b); } return retVal; } 
+6
source share

Windows CE is strongly tied to Unicode (most Win32 APIs do not even have ANSI analogues). Thus, CF does not do very well with ANSI, and it needs a little "help" in choosing the right one.

You can tell the marshal that you want to transfer the data as single-byte zero complete values ​​using the MarshalAs attribute ( MSDN docs clearly show that it is supported in CF), something like that:

 [DllImport("mydll.dll", SetLastError = true)] public static extern void Foo([MarshalAs(UnmanagedType.LPStr)]string myString); 
+2
source share

I find this marshal compiler useful, even if you're a little mistaken.

0
source share

All Articles