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

时间:2010-10-19 22:28:37

标签: c# c++ windows-mobile compact-framework interop

我有一个非托管c ++ DLL,我需要从 Windows Mobile C#app 调用。

我有C#包装器,它在桌面上运行良好。我可以从C#桌面程序调用DLL函数并传递字符串没有问题。

但是,当我编译lib和移动平台的包装器时,我在DllImport行中收到错误,指出CharSet.ANSI无法识别。我允许写的唯一选项是CharSet.Auto和CharSet.Unicode。

问题在于,无论此设置如何,c ++函数中接收的字符串都是宽字符串,而不是它们期望的纯字符串*。

我们可以使用wcstombs()来翻译每个c ++函数开头的所有字符串,但我宁愿不修改lib到这样的程度......

有没有办法修复与.NET Compact Framework一起使用的C#和C之间的编组?

3 个答案:

答案 0 :(得分:7)

不,没有。

Microsoft documentation指定:

  

[...] .NET Compact Framework   仅支持Unicode ,因此仅包含   CharSet.Unicode(和CharSet.Auto   它等于Unicode)值   不支持任何条款   声明声明。这意味着   ExactSpelling属性也不是   支持的。

     

因此,如果您的DLL功能   需要一个ANSI字符串   在DLL中执行转换,   或将字符串转换为字节数组   使用重载的GetBytes方法   之前的ASCIIEncoding类   从.NET开始调用该函数   Compact Framework将始终通过   指向Unicode字符串的指针。 [...]

解决方案是:

DLL中的函数

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

<强>包装

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

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

致电代码

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

答案 1 :(得分:2)

Windows CE严重偏向于Unicode(大多数Win32 API甚至没有ANSI等价物)。因此,CF也不能很好地使用ANSI,它需要一些“帮助”才能使其正确。

您可以通过使用MarshalAs属性(the MSDN docs清楚地表明它在CF中受支持)告诉编组程序您想要将数据作为单字节,空终止值传递,这些内容如下:< / p>

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

答案 2 :(得分:0)

我觉得这个marshal compiler很有用,即使它有点儿麻烦。

相关问题