Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/264.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/150.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从c+传递结构+;当结构仅在运行时已知时_C#_C++_Struct_Marshalling - Fatal编程技术网

C# 从c+传递结构+;当结构仅在运行时已知时

C# 从c+传递结构+;当结构仅在运行时已知时,c#,c++,struct,marshalling,C#,C++,Struct,Marshalling,我有以下问题: 我有一个C应用程序,它调用来自非托管C++ DLL的函数。在DLL中有一个初始化函数,它创建C++和C++之间的接口(基本上是一个值和它们的类型的列表),这些结构将存储在Stutt.< 之后,C#app会向dll发送一个回调函数,dll会每隔一段时间调用该函数,然后返回接口中定义的结构变量(或字节数组) 我的问题:如何传递和封送此结构?是否可以传递结构本身,还是应该传递字节数组 如果传递一个字节数组,当返回到C#应用程序时,您将如何封送它 我现在所拥有的: 在C#app中: 封送

我有以下问题:

我有一个C应用程序,它调用来自非托管C++ DLL的函数。在DLL中有一个初始化函数,它创建C++和C++之间的接口(基本上是一个值和它们的类型的列表),这些结构将存储在Stutt.< 之后,C#app会向dll发送一个回调函数,dll会每隔一段时间调用该函数,然后返回接口中定义的结构变量(或字节数组)

我的问题:如何传递和封送此结构?是否可以传递结构本身,还是应该传递字节数组

如果传递一个字节数组,当返回到C#应用程序时,您将如何封送它

我现在所拥有的:

在C#app中:

封送回调函数:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ProcessOutputDelegate(???); // not sure what should be here.
[DllImport("MyDLL.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void Test(ProcessOutputDelegate ProcessOutput);
ProcessOutputDelegate process = new ProcessOutputDelegate(ProcessOutput);
new thread(delegate() { Test(process); } ).Start();
导入dll函数:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ProcessOutputDelegate(???); // not sure what should be here.
[DllImport("MyDLL.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void Test(ProcessOutputDelegate ProcessOutput);
ProcessOutputDelegate process = new ProcessOutputDelegate(ProcessOutput);
new thread(delegate() { Test(process); } ).Start();
调用dll函数:

[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ProcessOutputDelegate(???); // not sure what should be here.
[DllImport("MyDLL.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern void Test(ProcessOutputDelegate ProcessOutput);
ProcessOutputDelegate process = new ProcessOutputDelegate(ProcessOutput);
new thread(delegate() { Test(process); } ).Start();
处理输出:

public void ProcessOutput(???)
{
    // Assume we have a list of values that describes the struct/bytes array.
}
<>在C++ DLL中,我有以下结构(这是一个例子,在不同的运行时间中可以调用不同的DLL):

以及C#app调用的函数:

\uuuu declspec(dllexport)无效测试(无效(*ProcessOutput)(接口*输出))
{
int i;
接口*输出=(接口*)malloc(sizeof(接口));
对于(i=0;i<100;i++)
{
睡眠(100);
输出->x=i;
输出->y=i/2;
输出->z=i/3;
ProcessOutput(output);//或从结构中生成字节数组
}
}
编辑:


C语言应用程序是一个通用的GUI,它假设显示一些C++ DLL执行的一些繁重的计算。在初始化过程中,dll会告诉GUI应该显示的变量(及其类型),GUI是根据这些方向构建的(同样,计算和变量可能会更改,值可能是int、float、chars…)。之后,dll运行,在每两个时间步中,它调用回调函数来更新GUI。这应该适用于任何实现此想法的dll:生成一个接口,然后根据此接口发送信息。

我不知道这是否是您问题的直接答案,但我用以下方法解决了它

  • 在DLL中调用GetResource并获取IntPtr:

    (...)
    IntPtr res = Native.GetResource();
    
  • 然后,为这个IntPtr实例化一个通用包装器:

    ResourceWrapper rw = new ResourceWrapper(res);
    
  • 如果要访问结构的特定字段,请在包装器上调用适当的方法:

    int field = rw.GetField();
    
  • 包装器调用DLL中的函数:

    (...)
    int result = Native.GetField(res);
    
  • DLL“重新对象化”调用:

    __declspec(dllexport) int __stdcall GetField(MyStructure * s)
    {
        return s->GetField();
    }
    
  • Struct获取数据(或引发异常、设置错误标志或返回错误等)

  • 此解决方案需要进行以下更改:

    • 数据结构应派生自同一基类
    • 如果可能的话,它们应该成为具有虚拟方法的类,允许访问它们的不同字段
    • 您必须实现某种安全机制,检查是否可以访问特定字段。最简单的是:

      __declspec(dllexport) BOOL __stdcall GetField(MyStruct * s, int & result)
      {
          result = 0;
          try
          {
              result = s->GetField();
          }
          catch(...)
          {
              return FALSE;
          }
      
          return TRUE;
      }
      
      以及:

      以及:


      • 我不知道这是否是对您问题的直接回答,但我用以下方法解决了它

      • 在DLL中调用GetResource并获取IntPtr:

        (...)
        IntPtr res = Native.GetResource();
        
      • 然后,为这个IntPtr实例化一个通用包装器:

        ResourceWrapper rw = new ResourceWrapper(res);
        
      • 如果要访问结构的特定字段,请在包装器上调用适当的方法:

        int field = rw.GetField();
        
      • 包装器调用DLL中的函数:

        (...)
        int result = Native.GetField(res);
        
      • DLL“重新对象化”调用:

        __declspec(dllexport) int __stdcall GetField(MyStructure * s)
        {
            return s->GetField();
        }
        
      • Struct获取数据(或引发异常、设置错误标志或返回错误等)

      • 此解决方案需要进行以下更改:

        • 数据结构应派生自同一基类
        • 如果可能的话,它们应该成为具有虚拟方法的类,允许访问它们的不同字段
        • 您必须实现某种安全机制,检查是否可以访问特定字段。最简单的是:

          __declspec(dllexport) BOOL __stdcall GetField(MyStruct * s, int & result)
          {
              result = 0;
              try
              {
                  result = s->GetField();
              }
              catch(...)
              {
                  return FALSE;
              }
          
              return TRUE;
          }
          
          以及:

          以及:


        我不理解C++结构“可能会改变”的部分。在普通C++中,结构是在编译时定义的。它们在运行时不会神奇地改变(当然是它们的内容,但不是它们的结构)。你能澄清一下吗?@Mat True,意思是在每个运行时可能会调用不同的dll,我将添加一个澄清。每个DLL都会实现“test”功能,但可能会构造不同的结构并执行不同的操作。因此,您尝试使用同一个C++接口,用于不同的C++ DLL,它们可能返回“完全不同的东西”。很抱歉,你的整件事听起来很奇怪。如果没有具体的例子来说明你在用什么,我想很难提供好的建议。如果是完全随机的东西,可能会与XML或JSON接口。很抱歉,在这种设置中,您可以只使用字节指针或其他东西,但是您要传递的结构的大小仍然未知,您需要以某种方式传递
        sizeof(interface)
        。一个值向量(类似于
        std::vector
        )不是一个可变结构。如果C代码不知道它会得到什么,它会收到什么?我不理解C++结构“可能会改变”的部分。在普通C++中,结构是在编译时定义的。它们在运行时不会神奇地改变(当然是它们的内容,但不是它们的结构)。你能澄清一下吗?@Mat True,意思是在每个运行时可能会调用不同的dll,我将添加一个澄清。每个DLL都会实现“test”功能,但可能会构造不同的结构并执行不同的操作。因此,您尝试使用同一个C++接口,用于不同的C++ DLL,它们可能返回“完全不同的东西”。我是