none
C#调用C++ RRS feed

  • 问题

  • C#与C++之间传递结构体数据,运行数次之后就会异常。

    报错信息:

    托管调试助手“ContextSwitchDeadlock”在“D:\Work\code\VS\Test2015\Test2015\CharpCaller\bin\Debug\CharpCaller.vshost.exe”中检测到问题。
    
    其他信息: CLR 无法从 COM 上下文 0xb99ef8 转换为 COM 上下文0xb99fb0,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消息的情况下处理一个运行时间非常长的操作。这种情况通常会影响到性能,甚至可能导致应用程序不响应或者使用的内存随时间不断累积。要避免此问题,所有单线程单元(STA)线程都应使用泵式等待基元(如 CoWaitForMultipleHandles),并在运行时间很长的操作过程中定期发送消息。


    C++  .h文件

    struct Person
    {
    public:
    	int id;
    	char name[256];
    };
    extern "C"
    {
    	__declspec(dllexport) void GetPerson(Person &person);
    };


    C++  .cpp文件

    void GetCPerson(CPerson &person)
    {
    	person.id = 1;
    
    	strcpy_s(person.name, 32, "名字Name-1");
    }


    C#

    [StructLayoutAttribute(LayoutKind.Sequential)]
    public struct Person
    {
        public int id;
            
        [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst =256)]
        public string name;
    }
    [DllImport("MFCLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "GetPerson")]
    extern static void GetPerson(IntPtr person);

    调用:

    Person p;
    
    for (int i = 0; i < 100000; i++)
    {
        int size = Marshal.SizeOf(typeof(Person));
        IntPtr pp = Marshal.AllocHGlobal(size);
        GetPerson(pp);
    
        p = (Person)Marshal.PtrToStructure(pp, typeof(Person));
    
        Marshal.FreeHGlobal(pp);
    
        Console.WriteLine("Person id: {0}, name: {1}", p.id, p.name);
    }


    • 已移动 Bob Ding 2017年8月29日 2:01
    2017年8月28日 10:12

答案

全部回复

  • 字符串也是一样的情况,难道不能一直调用吗?报的错是一样的。

    C++  .h文件

    extern "C"
    {
    	__declspec(dllexport) void PassString2(char *str);
    };

    C++  .cpp文件

    void PassString2(char *str)
    {
    	if (0 == strcmp(str, "C#"))
    	{
    		strcpy_s(str, 32, "I'm(我是)C++");
    	}
    }

    C#

    [DllImport("MFCLib.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "PassString2")]
    extern static void PassString2(StringBuilder arg);

    调用

    private void callBtnPassString2_Click(object sender, RoutedEventArgs e)
    {
        StringBuilder sb = new StringBuilder("C#", 256);
        for (int i = 0; i < 1000000; i++)
        {
            PassString2(sb);
            Console.WriteLine("Person out args: {0}", sb);
        }
    }
    2017年8月29日 0:50
  • 你好,

    由于这个问题和WPF没有直接关系,我把你的问题移到 .NET Framework 一般性问题讨论区 ,你可以在这里得到更专业的答复。

    感谢你的理解和合作!

    Best Regards,

    Bob


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年8月29日 2:01
  • 非常感谢~

    目前使用2种方式调用C++都遇到问题,一头雾水!

    2017年8月29日 2:11
  • Hi,

    感谢你在MSDN论坛发帖。

    我个人认为,结构体在C#中是被定义成值类型,所以你在方法中传送person这个结构体的时候,你可以尝试使用。

    ByRef r As Person

    因为你传的是结构体的引用,在C++中引用是引用他人的地址,这个地址不应该在C#代码中释放,我认为这个地方可以。

    在引用这个词上面,英文有了一个indirection来表示在CLR中来欺骗编译器。

    这边微软提供一个实例。

    BOOL PtInRect(const RECT *lprc, POINT pt);  
    Declare Auto Function PtInRect Lib "user32.dll" _  
        (ByRef r As Rect, p As Point) As Boolean  

    更详细的信息,你可以看一下这个文章,希望对你有所帮助。

    Best Regards,

    Hart


    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    2017年8月29日 8:34
    版主
  • 从C++转C#,建议您使用PInvoker.NET免费转换工具:

     PInvoke Interop Assistant


    Reproduce your quesions with ScreenToGif is your choice.
    For IIS: IIS Forum,
    For WebSite of .NET: ASP.NET Forum,
    For others: StackExchange.
    For spam-sender or forum urgent issues, Send your Email at:  forumsfeedback@microsoft.com

    • 已标记为答案 oneonce 2017年9月13日 6:20
    2017年9月1日 10:59
    版主