C# 本机dll的.net包装器-如何最大限度地降低运行时错误的风险?

C# 本机dll的.net包装器-如何最大限度地降低运行时错误的风险?,c#,.net,c++,dll,wrapper,C#,.net,C++,Dll,Wrapper,我正在开发一个C#应用程序。由于我在C/C++中有一些最小二乘拟合算法,这也太麻烦了,所以我把C++代码变成了一个DLL,然后用C语言创建了一个包装器。 在C代码中,我定义了一个结构,它作为指针传递给非托管C++代码。结构包含拟合函数的初始猜测,还用于返回拟合结果 在我看来,您必须在托管代码和非托管代码中定义结构。但是,将来使用我的源代码的人可能会决定更改C#应用程序中结构的字段,而不知道他们也必须更改本机代码中的结构。这最多会导致运行时错误(更糟糕的是会产生错误的结果),但不会有错误消息告诉开

我正在开发一个C#应用程序。由于我在C/C++中有一些最小二乘拟合算法,这也太麻烦了,所以我把C++代码变成了一个DLL,然后用C语言创建了一个包装器。 <>在C代码中,我定义了一个结构,它作为指针传递给非托管C++代码。结构包含拟合函数的初始猜测,还用于返回拟合结果

在我看来,您必须在托管代码和非托管代码中定义结构。但是,将来使用我的源代码的人可能会决定更改C#应用程序中结构的字段,而不知道他们也必须更改本机代码中的结构。这最多会导致运行时错误(更糟糕的是会产生错误的结果),但不会有错误消息告诉开发人员/最终用户出了什么问题

从我的理解中,不可能在非托管C++ DLL中创建一个测试,它检查结构是否包含正确的字段,但它是否可以使DLL返回正确格式的结构到C.*包装器?

否则,有什么方法可以降低将来一些粗心的程序员导致难以检测的运行时错误的风险

示例代码:

//C++
struct InputOutputStruct {
    double a,b,c;
}

extern "C" __declspec(dllexport) void DoSomethingToStruct(InputOutputStruct* s)
{
//。。。算法

}

//C#
using System.Runtime.InteropServices;
[StructLayout(LayoutKind.Sequential)]
    public struct InputOutputStruct {
        public double a,b,c;
    }

[DllImport("CpluplusDll.dll")]
    public static unsafe extern bool DoSomethingToStruct(InputOutputStruct* s);

class CSharpWrapper {
    static void Main(string[] args)
    {
        InputOutputStruct s = new InputOutputStruct();
        unsafe {
            InputOutpustruct* sPtr = &s;
            DoSomethingToStruct(sPtr);
            s = *sPtr;
        }
    }
}
但是,是否有可能让DLL将正确格式的结构返回给C#wrapper

我不这么认为,因为您总是需要在C#端定义结构

以下是一个可能有效的解决方案(从未测试过):
  • 在两侧为每个共享的结构指定一个唯一标识符(GUID、宏)
  • 为C++创建一个包含C++和C++侧的类型信息的反射。这可以通过使用宏来完成 <> LI>使用GUID、反射和宏比较C++结构和C结构在启动时的性能。您还可以使用
    sizeof
    首先比较大小

  • 那可能需要很多工作
  • 当你在C++方面工作时,当你不知道宏
  • 时,你仍然会犯很多错误。
在我看来,您必须在托管和 以及非托管代码


不是真的。这是C++ C++ C++语言编写的,它方便了C++与.net .</P>的交互操作:BoL的大小与C++不同(谢谢):我已经改变了我的代码,当然可以使用C++/CLI,但也许他被钉在纯C/C++上。@菲利克斯:关于它没有什么“C/C++”。他正在使用C++。这里没有C。他说
C/C++
,但这并不重要。也许dll必须用C/C++编写,这是我想指出的。如果他能使用C++/CLI,你的答案正是他所需要的。谢谢大家。我有一些C代码,但是在这个论坛上读了一点之后,我得出结论,可以将文件重命名为.cpp,以便能够使用/clr选项进行编译。不过,我意识到这不是一个很好的解决方案。我使用的c文件是这里的最小二乘拟合函数: