如何从c#调用C ++函数

时间:2011-11-09 08:37:30

标签: c# pinvoke

我试图调用C#中的大学提供的C ++函数。他为我提供了一个dll和以下头文件。

C ++标题

#include "../libs/tfvo.h"

extern "C" __declspec(dllexport) vector<double> fvm(
            vector<double> yearFractions,   
            vector<double> discountFactors, 
            vector<double> weightings,      
            double alpha_meanReversion,     
            double sigma_meanReversion,     
            double alpha_shortRate,         
            double alpha_meanReversion,
            double sigma_shortRate,         
            vector<double> startingValues = vector<double>(3,0.01));

我使用以下C#代码调用上面的c ++函数,导致以下错误。

  

“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。”

如何在C#中调用此函数? C ++代码是否需要更改?

C#

var result = SimpleDllTest.testWrapper(); // In a console app

class SimpleDllTest
{
    [DllImport("fvm.dll")]
    public static extern IntPtr fitVasicekModel(
        IntPtr yearFractions,
        IntPtr weightings,
        double alpha_meanReversion,     
        double sigma_meanReversion,     
        double alpha_shortRate,         
        double sigma_shortRate,
        IntPtr startingValues
        );


    public static double [] testWrapper()
    {

        var t = new double[] { 0.1, 1.2 };
        var v = new double[] { 0.1, 1.2 };

        int size = Marshal.SizeOf(t[0]) * t.Length;
        IntPtr pnt = Marshal.AllocHGlobal(size);
        Marshal.Copy(t, 0, pnt, t.Length);

        int sizev = Marshal.SizeOf(v[0]) * v.Length;
        IntPtr pntv = Marshal.AllocHGlobal(sizev);
        Marshal.Copy(v, 0, pntv, v.Length);

        IntPtr result = fitVasicekModel(pnt, pnt, 1, 1, 1, 1, pntv);
        try
        {
            return (double[])Marshal.PtrToStructure(result , typeof(double[]));
        }
        finally
        {
            // Free the pointer here if it's allocated memory
        }
    }
}           

更多背景: 我的大学已经开发了几个与财务相关的计算,我希望我们可以用最小的努力将他的整个库重用到另一个C#应用程序中。他和我在这方面的经验非常少(创建可导出的C ++代码并在C#中使用它),所以任何其他提示等都会受到欢迎。

2 个答案:

答案 0 :(得分:1)

您无法直接从C#调用此函数。 vector<>与C#int[]无关。

最好的办法是将C#库包装在一个manged C ++包装器中,这样你就可以在进程中从C#类型转换为C ++类型,并从C ++类型到C#类型的映射出路。

答案 1 :(得分:0)

如果您与库的开发人员合作(仅仅使用他的lib),可能值得看看他提供的C ++ CLI构建,您可以直接使用标准C#。您需要处理lib代码中的vector / stl用法 - 用cli Lists(或其他托管容器)替换它或找到包装器解决方案(有关于例如here和{{3}的各种SO帖子})。
我认为这可能比基于pinvoke的互操作到原始C ++更容易长期解决。