[英]Calling C++ thread from C#
我是C ++的新手。 由于某些原因,我需要做一个流动模型。
步骤1:我在C ++中有一个Method1
,它将更改从C#传递的变量的值。 我称该变量为str
。
步骤2:创建一个线程,并在几毫秒后将str
更改为另一个值。
在C ++中:
char* temp; // Temporary pointer
void Thread1(void* arr)
{
Sleep(1000); // Wait for one second
strcpy_s(temp, 100, "Thread 1"); // Change value of str to ‘Thread 1’ -> A exception was threw because ‘temp’ is undefined
}
__declspec(dllexport) void Method1(char* str)
{
temp = str; // Keep pointer of ‘str’ to temporary pointer to change ‘str’ value in Thread
strcpy_s(temp, 100, "Method 1"); // Change ‘str’ to ‘Method 1’. -> It work OK
_beginthread(Thread1, 0, NULL); // Start Thread1
}
在C#中:
public static StringBuilder str = new StringBuilder(100);
[DllImport("C++.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Method1(StringBuilder test);
static void Main(string[] args)
{
Method1(str); // Call Method1 in C++ dll.
Console.WriteLine(str.ToString()); // Result: “Method 1” -> OK
while (true)
{
Console.WriteLine(str.ToString()); // Print str value every 0.1 second. It exception after 1 second
Thread.Sleep(100);
}
}
当结果Method1
被调用时, str
改为Method1
,但是当Thread1
运行:指针temp
为空,所以引发了异常。 请提供一些见解,我怎么可以改变str
的Thread1
。
非常感谢。
您不能为此使用StringBuilder
。 这是因为封送处理假定对象仅在函数执行期间使用(即,假定函数返回后本机代码将不再使用该对象)。 C ++不知道StringBuilder
是什么,因此运行时仅在P / Invoke调用期间通过缓冲区提供对它的访问。
您应该分配一些内存,并将其传递给函数。 这是一种可行的方法:
[DllImport("C++.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Method1(byte* test);
接着:
unsafe
{
var buffer = new byte[100]; // a C++ char is 1 byte
fixed (byte* ptr = buffer)
{
Method1(ptr);
while (true)
{
// WARNING: There's no locking here (see comment below)
// It may cause undefined behavior.
var str = Encoding.ASCII.GetString(buffer);
Console.WriteLine(str);
Thread.Sleep(100);
}
}
}
在整个C ++代码访问缓冲区期间,缓冲区必须保持固定( fixed
)状态。
请注意,这仍然是不安全的:
strcpy_s
的值)。 这是隐式的。 最好将缓冲区大小传递给函数。 您不应将字符串复制到未分配的指针。 实际上,当您使用指针时,这只是一个地址(4个字节),因此您没有足够的空间来复制字符串。
将char * temp更改为char temp [100]。
这样,您要求内存给您100字节来复制数据。
这应该工作
变量temp只是一个指针,您的赋值temp = str; 仅将指针分配给字符串指针。 关键是您永远不会为临时内存分配内存。 考虑到这一点,在调用线程之后,str参数超出范围并被取消分配,因此您的临时指针现在无效。
感谢所有答案。 最后,我基于Lucas Trzesniewski的解决方案和我的代码。 我将C#代码更改为:
[DllImport("C++.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void Method1(byte[] str);
static void Main(string[] args)
{
var buffer = new byte[100]; // a C++ char is 1 byte
Method1(buffer);
while (true)
{
var str = Encoding.ASCII.GetString(buffer);
Console.WriteLine(str);
Thread.Sleep(100);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.