我有一个需要从C#调用的C ++ DLL。 dll中的一个函数需要char *作为输入参数,另一个函数使用char *作为输出参数。
从C#调用这些内容的正确方法是什么?
答案 0 :(得分:3)
字符串应该有效,如果方法修改了字符串,则应使用StringBuilder。
以下参考示例:
[DllImport ("libc.so")]
private static extern void strncpy (StringBuilder dest,
string src, uint n);
private static void UseStrncpy ()
{
StringBuilder sb = new StringBuilder (256);
strncpy (sb, "this is the source string", sb.Capacity);
Console.WriteLine (sb.ToString());
}
如果你不知道p / invoke marshaling是如何工作的,你可以阅读http://www.mono-project.com/Interop_with_Native_Libraries
如果您只是在使用字符串,请阅读以下部分:http://www.mono-project.com/Interop_with_Native_Libraries#Strings
答案 1 :(得分:2)
使用字符串对输入参数可以正常工作,但您可以使用MarshalAs属性控制有关字符串的详细信息。 E.g。
[DllImport("somedll.dll", CharSet = CharSet.Unicode)]
static extern void Func([MarshalAs(UnmanagedType.LPWStr)] string wideString);
至于返回char *参数,由于涉及对象所有权,这有点复杂。如果您可以更改C ++ DLL,则可以使用CoTaskMemAllocate,例如:
void OutputString(char*& output)
{
char* toCopy = "hello...";
size_t bufferSize = strlen(toCopy);
LPVOID mem = CoTaskMemAlloc(bufferSize);
memcpy(mem, toCopy, bufferSize);
output = static_cast<char*>(mem);
}
然后C#端只使用'out string'参数,垃圾收集器可以获取字符串的所有权。
另一种方法是使用StringBuilder,但是在实际调用函数之前你需要知道字符串的大小。
答案 2 :(得分:0)
不确定这是否有效,但您是否尝试过使用
StringObject.ToCharArray();
不确定从char * tho初始化String。 Mybe只是分配给一个字符串对象,值得一试。
答案 3 :(得分:0)
你试过StringBuilder吗?我在Google搜索中找到了这个:
[DllImport("advapi32.dll")]
public static extern bool GetUserName(StringBuilder lpBuffer, ref int nSize);
如果你发布了正在发出的电话,我们可以帮你组装。
答案 4 :(得分:0)
如果DLL函数期望分配char*
的缓冲区(而不是宽/多字节缓冲区),则可以执行以下操作:
[DllImport("somedll.dll", CharSet = CharSet.Ansi)]
static extern void TheFunc(byte[] someBuffer, int someSize);
这里,将在c#中分配的缓冲区传递到TheFunc
,该缓冲区用一个字符字符串(char类型)填充。字节不是由C#“解释”的,它们被视为8位整数,因此非常适合保存8位字符。
因此,一个示例代码将被删除:
byte[] mybuffer;
int bufSize;
bufSize = 2048;
mybuffer = new byte[bufSize];
TheFunc(mybuffer, bufSize);
string value;
for(value = "", int ix = 0; (mybuffer[ix] != 0) && (ix < bufSize); ix++)
value += (char) mybuffer[ix];
DoSomethingWithTheReturnedString(value);