Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.net wrapper for native dll - how to minimize risk of run-time error?

I am developing a C# application. Since I have some algorithms for least-squares fit in C/C++ that would be too cumbersome too translate, I have made the C++ code into a dll and then created a wrapper in C#.

In the C# code, I have defined a struct that is passed to the unmanaged C++ code as a pointer. The struct contains the initial guesstimates for the fitting functions, and it is also used to return the results of the fit.

It appears to me that you must define the struct in both the managed and the unmanaged code. However, someone using my source code in in the future might decide to change the fields of the struct in the C# application, without understanding that they also have to change the struct in the native code. This will result in a run-time error at best (and produce erroneous results at worse), but there will be no error message telling the developer / end user what is wrong.

From my understanding, it impossible to create a test in the unmanaged C++ DLL that checks if the struct contains the correct fields, but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?

Otherwise, what ways are there to reduce the risk that some careless programmer in the future causes run-time errors that are hard to detect?

Sample code:

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

extern "C" __declspec(dllexport) void DoSomethingToStruct(InputOutputStruct* s)
{

// ... algorithm

}

//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;
        }
    }
}
like image 672
user1083059 Avatar asked Dec 06 '11 08:12

user1083059


2 Answers

It appears to me that you must define the struct in both the managed and the unmanaged code.

Not true. This is what C++/CLI was invented for- facilitate much easier interoperation with C++ and .NET.

like image 94
Puppy Avatar answered Oct 17 '22 00:10

Puppy


but is it posible to have the DLL returning a struct of the correct format to the C# wrapper?

I don't think so, because you always need to define the structs on the C# side.

Here are a solution which may work ( never tested ):

  • Give each struct which is shared a unique identifier on both sides ( GUID, Macros )
  • Create a reflection for C++ which contains informations about the the types which are used on C# and C++ side. This could be done by using macros.
  • Compare the C++ structs and the C# structs on startup by using the GUIDs, reflection and macros. You can also use sizeof to compare sizes first.

  • That could be a lot of work
  • When working on C++ side you still can make a lot of things wrong when you not know about the macros
like image 31
Felix K. Avatar answered Oct 16 '22 23:10

Felix K.