3

I'm programming C# code that imports a C++ function similar to this:

//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;
}

To import this function to C# I've tried 2 methods and both have resulted in a System.AccessViolationException. That means I'm trying to access protected memory...

//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
}

Up until now, I've thought it was a problem with my C# code, but would the C++ code's use of an array cause a problem? Am I missing something really obvious here?

8
  • 6
    You did not declare the function correctly. You must use CallingConvention.Cdecl in the [DllImport] attribute since you didn't use __stdcall in the C declaration. The C++ code cannot compile and the "structs and arrays" you mention in your question title are quite invisible btw. You make it very difficult to help you. Commented Jul 7, 2014 at 17:42
  • I think when you are exporting functions from your C/C++ library, you should use IntPtr in .Net in order to have access to them. Whether they are safe/unsafe it's a different question. It all depends how well you write your code. Commented Jul 7, 2014 at 17:43
  • @armanali. How would an intPtr help? Do you see a reason to use it other than 'because it is there?" (PS: An intPtr lets C# do pointer arithmetic. I don't see any pointer arithmetic.) Commented Jul 7, 2014 at 17:50
  • Oops my bad; it still isn't working. Switched Calling convention to Cdecl. Still getting error. I forgot to call the function in my test script. Commented Jul 7, 2014 at 18:41
  • @generic this is the first time I've seen someone use both c and c++ tags correctly! Commented Jul 7, 2014 at 22:33

1 Answer 1

2

This isn't a problem with your C# p/invokes or the signature of the native function foo. Aside from your C++ array syntax and what exactly RandomFunction does, everything works fine. I've just tested with my own little demo:

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"
}

I only have a few differences from what you have:

  • My C++ arrays are declared using the standard syntax double dubs [10].
  • My compiler requires two underscores in the __declspec syntax
  • I'm compiling everything using Visual Studio 2012, in 64-bit, on Windows 7 SP 1.
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.