Cristian M
Cristian M

Reputation: 725

How to correctly call methods from unmanaged C++ DLL in C#?

I have an acquisition board controlled with a C++ API. I want to call the methods directly from my C# application.

These are the methods which cause problems:

DLL:

// Read the DATA of the board
SPINAPI int pb_get_data(unsigned int num_points, int *real_data, int *imag_data);
// Write plain ASCII file for the data returned from pb_get_data(..)
SPINAPI int pb_write_ascii(const char *fname, int num_points, float SW, float SF, const int *real_data, const int *imag_data);

where SPINAPI is defined as follows:

#ifdef __WINDOWS__
#ifdef DLL_EXPORTS 
#define SPINAPI __declspec(dllexport)
#else
#define SPINAPI __declspec(dllimport)
#endif
#else
#define SPINAPI
#endif

C#:

[DllImport(@"C:\SpinCore\SpinAPI\lib32\spinapi.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int pb_get_data(uint num_points, [MarshalAs(UnmanagedType.LPArray)] ref int[] real_data, [MarshalAs(UnmanagedType.LPArray)] ref int[] imag_data);

[DllImport(@"C:\SpinCore\SpinAPI\lib32\spinapi.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int pb_write_ascii(string fname, int num_points, float SW, [MarshalAs(UnmanagedType.LPArray)] ref int[] real_data, [MarshalAs(UnmanagedType.LPArray)] ref int[] imag_data);

When calling pb_get_data(),

pb_get_data((uint)numberOfPoints, ref idata, ref idata_imag);

I get the following error:

System.AccessViolationException was unhandled

Message: An unhandled exception of type 'System.AccessViolationException' occurred in Unknown Module.
Additional information: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

When calling pb_write_ascii(),

pb_write_ascii(@"data\direct_data_0.txt", numberOfPoints, (float)actualSW, ref idata, ref idata_imag);

where:

int[] idata = new int[MAX_NUMBER_POINTS];
int[] idata_imag = new int[MAX_NUMBER_POINTS];

nothing happens (the file is not written).

Does anybody have an idea about what I'm doing wrong and how to correct the problems? I mention that I could successfully call other methods from the DLL.

Upvotes: 0

Views: 137

Answers (2)

Cristian M
Cristian M

Reputation: 725

According to Hans Passant, eliminating the ref keyword was causing the problem. Removing it resolved the issue.

Upvotes: 1

Alex Aparin
Alex Aparin

Reputation: 4522

Usage of C++/Cli wrapped library can be possible solution. You should create C++/Cli library, which will contain such code:

namespace ManagedCode {

    public ref class WrappedFunctions
    {
    public: 
        static int pb_get_data(unsigned int num_points, array<int>^ real_data, array<int>^ imag_data)
        {
            pin_ptr<int> temp_real_data = &real_data[0];
            pin_ptr<int> temp_imag_data = &imag_data[0];
            return UnManagedCode::pb_get_data(num_points, temp_real_data, temp_imag_data);
        }
    };
}

In other cases, you can use marshalling functions

For detailed information, read https://msdn.microsoft.com/ru-ru/library/1dz8byfh.aspx

Upvotes: 0

Related Questions