繁体   English   中英

从C#调用C ++线程

[英]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为空,所以引发了异常。 请提供一些见解,我怎么可以改变strThread1

非常感谢。

您不能为此使用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 )状态。

请注意,这仍然是不安全的:

  • 没有锁,因此C#代码可能在C ++代码写入字符串的同时读取字符串。 这可能会导致未定义的行为。
  • 您的缓冲区必须至少100个字节(由于提供给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.

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