使用DllImport有很多关于某些特定问题的文章。 唉,我常常看到对同一个问题的不同回复。 例如有人说如果一个c ++函数返回一个char *和一个int * strLen,那么有人说我应该在我的dllImport语句中使用StringBuilder而其他人说返回byte [],有些人在dllImport中有一个marshall语句,有些人不赞成“T。由于旧的C#/ .net版本,似乎需要一些答案。
所以问题是:如果来自c ++的dll调用相当简单,没有奇怪的调用约定或其他奇怪的项目,如果你有输出char *和size或者输入char *和size,相应的DllImport函数应该是什么?
c++ .h
bool SendString(const char* pSendStr, long strSize);
bool ReadString(char* pReadStr, long& readStrSize);
相应的DllImports是什么?用字符串替换instr和outstr? StringBuilder的?的char []?字节[]?是否需要任何元帅声明?
答案 0 :(得分:5)
bool SendString(const char* pSendStr, long strSize);
这个功能很简单。文本从调用者发送到被调用者。 p / invoke声明如下:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool SendString(string SendStr, int Len);
请注意,我假设cdecl调用约定,因为这是C ++代码的默认值。并且还要注意Windows上的C ++中的long
是32位宽。所以它匹配C#中的int
。
调用函数时,需要传递字符串及其长度。但是,常规约定是使用以null结尾的字符串,因此不需要length参数。我会声明这样的非托管函数:
bool SendString(const char* pSendStr);
这样的p / invoke:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool SendString(string SendStr);
另一个功能稍微复杂一些。你已经宣布它是这样的:
bool ReadString(char* pReadStr, long& readStrSize);
这里调用者分配由被调用者填充的缓冲区。您可以使用StringBuilder
作为文本,让编组人员为您完成工作。 p / invoke是:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
static extern bool ReadString(StringBuilder ReadStr, ref int Len);
约定是您提供提供的缓冲区的长度。反过来,该函数将让您知道它写了多少个字符。你可以这样调用这个函数:
int len = 256;
StringBuilder ReadStr = new StringBuilder(len);
bool succeeded = ReadString(ReadStr, ref len);
if (succeeded)
{
string str = ReadStr.ToString();
}
答案 1 :(得分:2)
正如leppie所写,你通常想要的是:
[DllImport(my.dll)]
static extern bool SendString(string sendString, int stringSize);
[DllImport(my.dll)]
static extern bool ReadString(StringBuilder readString, ref int readStringSize);
这将为您自动转换为Unicode(和返回)。
如果要精确访问char *,可以使用byte []。这样就不会进行转换,您可以更好地控制正在进行的操作。通常你不会需要它。一个用例可能是当你的char *包含\ 0 chars。
时