简体   繁体   English

在Windows Mobile中将C#字符串传递给非托管C DLL

[英]Passing a C# string to an unmanaged C DLL in Windows Mobile

I've got an unmanaged c++ DLL that I need to call from a Windows Mobile C# app . 我有一个非托管的c ++ DLL,我需要从Windows Mobile C#应用程序调用。

I've got the C# wrapper and it works nicely in desktop. 我有C#包装器,它在桌面上很好用。 I can call the DLL functions from a C# desktop program and pass strings around with no problem. 我可以从C#桌面程序调用DLL函数并传递字符串没有问题。

However, when I compile the lib and the wrapper for the mobile platform, I get an error in the DllImport lines saying that the CharSet.ANSI is not recognized. 但是,当我编译lib和移动平台的包装器时,我在DllImport行中收到错误,指出CharSet.ANSI无法识别。 The only options I'm allowed to write are CharSet.Auto and CharSet.Unicode. 我允许写的唯一选项是CharSet.Auto和CharSet.Unicode。

The problem is that, regardless of this setting, the strings that are received in the c++ functions are wide char strings, and not plain char* strings that is what they expect. 问题在于,无论此设置如何,在c ++函数中接收的字符串都是宽字符串,而不是它们所期望的普通char *字符串。

We can use wcstombs() to translate all strings at the beginning of each c++ function, but I'd rather not modify the lib to such an extent... 我们可以使用wcstombs()来翻译每个c ++函数开头的所有字符串,但我宁愿不修改lib到这样的程度......

Is there a way to fix the marshalling between C# and C that works with the .NET Compact Framework? 有没有办法修复与.NET Compact Framework一起使用的C#和C之间的编组?

No, there isn't. 不,没有。

Microsoft documentation specifies that: Microsoft文档指定:

[...] the .NET Compact Framework only supports Unicode , and consequently only includes the CharSet.Unicode (and CharSet.Auto which equals Unicode) value, and does not support any of the clauses of the Declare statement. [...] .NET Compact Framework 仅支持Unicode ,因此仅包含CharSet.Unicode(和CharSet.Auto等于Unicode)值,并且不支持Declare语句的任何子句。 This means that the ExactSpelling property is also not supported. 这意味着也不支持ExactSpelling属性。

As a result, if your DLL function expects an ANSI string, you'll need to perform the conversion in the DLL, or convert the string to a byte array using the overloaded GetBytes method of the ASCIIEncoding class , before calling the function, since the .NET Compact Framework will always pass a pointer to the Unicode string. 因此,如果您的DLL函数需要ANSI字符串,则需要在DLL中执行转换,或者在调用函数之前使用ASCIIEncoding类的重载GetBytes方法将字符串转换为字节数组 ,因为.NET Compact Framework将始终传递指向Unicode字符串的指针。 [...] [...]

The solution is: 解决方案是:

Functions in the DLL DLL中的函数

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

Wrapper 包装纸

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

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

Calling 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;
}

Windows CE is heavily biased toward Unicode (most Win32 APIs don't even have ANSI equivalents). Windows CE严重偏向于Unicode(大多数Win32 API甚至没有ANSI等价物)。 As such, the CF doesn't really do well with ANSI either and it needs a little "help" in getting it right. 因此,CF也不能很好地使用ANSI,它需要一些“帮助”才能使其正确。

You can tell the marshaler that you want to pass the data as single-byte, null terminated values by using the MarshalAs attribute ( the MSDN docs clearly show it is supported in the CF), something along these lines: 您可以通过使用MarshalAs属性告诉编组器您想要将数据作为单字节,空终止值传递( MSDN文档清楚地表明它在CF中受支持),这些内容如下:

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

我觉得这个编组编译器很有用,即使你有点马车。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM