从C#调用不安全的C ++时出现System.AccessViolationException

时间:2014-07-07 17:31:27

标签: c# c++ c arrays struct

编写C#代码,导入类似于此的C ++函数:

//C++ code
extern "C" _declspec(dllexport) int foo(double *var1, double *var2){
    double dubs[10];
    RandomFunction(dubs);
    *var1 = dubs[5];
    *var2 = dubs[7];
    return 0;
}

要将此功能导入C#,我尝试了2种方法,两者都导致了System.AccessViolationException。这意味着我试图访问受保护的内存......

//C# import code
//method 1
[DllImport(example.dll,CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int foo(ref double var1, ref double var2);
//method 2
[DllImport(example.dll,CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern int foo(double *var1, double *var2);

//C# calling code
//method 1
public unsafe int call_foo(){
    ....Stuff
    double var1 = 0;
    double var2 = 0;
    foo(ref var1, ref var2);
    ....More Stuff
}
//method 2
public unsafe int call_foo(){
    ....Stuff
    double var1 = 0;
    double var2 = 0;
    double *v1 = &var1;
    double *v2 = &var2;
    foo(v1, v2);
    ....More Stuff
}

到目前为止,我一直认为这是我的C#代码的问题,但是C ++代码使用数组会导致问题吗?我错过了一些非常明显的东西吗?

1 个答案:

答案 0 :(得分:2)

这不是您的C#p / invokes或本机函数foo的签名的问题。除了你的C ++数组语法以及RandomFunction完全正确的内容之外,一切正常。我刚用我自己的小演示测试过:

C ++:

void RandomFunction( double dubs[] );

extern "C" __declspec(dllexport) int foo ( double* var1, double* var2 ) 
{
    double dubs[10];

    RandomFunction( dubs );

    *var1 = dubs[5];
    *var2 = dubs[7];

    return 0;
}

void RandomFunction( double dubs[] ) {
    for ( int i = 0; i < 10; i++ ) {
        dubs[i] = i;
    }
}

C#:

[DllImport( "Native.dll", CallingConvention = CallingConvention.Cdecl )]
private static extern int foo( ref double var1, ref double var2 );

public static void Main( string[] args )
{
    FooTest();
}

private static void FooTest()
{
    double var1 = 0;
    double var2 = 0;

    foo( ref var1, ref var2 );

    Console.Out.WriteLine( "Var1: {0:0.0}; Var2: {1:0.0}", var1, var2 );
    // Prints "Var1: 5.0; Var2: 7.0"
}

我与你所拥有的只有一些区别:

  • 我的C ++数组使用标准语法double dubs [10]声明。
  • 我的编译器在__declspec语法
  • 中需要两个下划线
  • 我在Windows 7 SP 1上使用Visual Studio 2012(64位)编译所有内容。