15

I have an unmanaged dll with a class "MyClass" in it. Now is there a way to create an instance of this class in C# code? To call its constructor? I tried but the visual studio reports an error with a message that this memory area is corrupted or something.

Thanks in advance

4
  • 1) static void Main(string[] args) { IntPtr p = new IntPtr(); Program.CreateObserv(ref p); } [DllImport(@"C:\mm_2008\liba.dll", EntryPoint = "??0CRls@fld@@QAE@ABV01@@Z", SetLastError = true, CallingConvention = CallingConvention.ThisCall)] internal static extern void CreateObserv(ref IntPtr p); this code throws an AccessViolationException: accessviolationexception attempted to read or write protected memory... Commented Apr 14, 2010 at 12:00
  • 2) static void Main(string[] args) { IntPtr p = Program.CreateObserv(); } [DllImport(@"C:\mm_2008\liba.dll", EntryPoint = "??0CRls@fld@@QAE@ABV01@@Z", SetLastError = true, allingConvention = CallingConvention.ThisCall)] internal static extern IntPtr CreateObserv(); - this code crushes the application and app host Commented Apr 14, 2010 at 12:01
  • To avoid mangled entry point names like "??0CRls@fld@@QAE@ABV01@@Z", use extern "C" in unmanaged Dll. Function declared as extern "C" is exported without name mangling. Commented Apr 14, 2010 at 12:11
  • 1
    @Evgeny007 don't put code in comments, delete your comments and put the code in the question. Commented Dec 7, 2016 at 17:21

3 Answers 3

23

C# cannot create class instance exported from native Dll. You have two options:

  1. Create C++/CLI wrapper. This is .NET Class Library which can be added as Reference to any other .NET project. Internally, C++/CLI class works with unmanaged class, linking to native Dll by standard C++ rules. For .NET client, this C++/CLI class looks like .NET class.

  2. Write C wrapper for C++ class, which can be used by .NET client with PInvoke. For example, over-simplified C++ class:

    class MyClass()
    {
    public:
        MyClass(int n){data=n;}
        ~MyClass(){}
        int GetData(){return data;}
    private:
        int data;
    };

C API wrapper for this class:

    void* CreateInstance()
    {
        MyClass* p = new MyClass();
        return p;
    }

    void ReleaseInstance(void* pInstance)
    {
        MyClass* p = (MyClass*)pInstance;
        delete p;
    }

    int GetData(void* pInstance)
    {
        MyClass* p = (MyClass*)pInstance;
        return p->GetData();
    }

    // Write wrapper function for every MyClass public method.
    // First parameter of every wrapper function should be class instance.

CreateInstance, ReleaseInstance and GetData may be declared in C# client using PInvoke, and called directly. void* parameter should be declared as IntPtr in PInvoke declaration.

Sign up to request clarification or add additional context in comments.

5 Comments

You miss an extern "C" in the wrapper functions.
Danvil - this is what I wrote in the question note. Anyway, thanks, I really feel better now.
@Alex What if there is a hierarchy of classes in the native C++ dll...??
What makes it a "C" API? Aren't new and delete C++ constructs? Seems like just a static C++ API
@Rotem: I mean, this wrapper is available for C client, as well as any client working with C-style API: .NET PInvoke, Assembly, Delphi etc. Wrapper itself is implemented in C++.
3

The solution is create C++/CLI wrapper like:

#include "DllExportClass.h"

public ref class ManagedOperationHelper
{
    public:

    double Sum(double add1, double add2)
    {
        CDllExportClass obj;
        double ret=obj.Sum(add1, add2);
        return ret;
    }

    double Mult(double mult1, double mult2)
    {
        CDllExportClass obj;
        double ret=obj.Mult(mult1, mult2);
        return ret;
    }
};

where CDllExportClass is the class exported from native code. Above is the .h of the C++/CLI. Take care to let find the lib to this dll. Put the dll and the lib in the same directory and compile the C++/CLI code.In the managed code directory put the native dll and the C++/CLI dll. In the managed project put the reference of the C++/CLI project. Instanciate in the maged code the C++/CLI class like:

ManagedOperationHelper obj = new ManagedOperationHelper();
double ret=obj.Sum(10, 20);  

It's all.

Comments

2

You can not use unmanged C++ code directly in C#. The interoperability can be done using PInvoke. There are a lot of issues related to this topic, especially when calling functions which have pointers as arguments.

The basic procedure goes like this:

C# part

namespace MyNamespace {
  public class Test {
    [DllImport("TheNameOfThe.dll")]
    public static extern void CreateMyClassInstance();
    
    public void CallIt() {
        CreateMyClassInstance(); // calls the unmanged function via PInvoke
    }
  }
}
    

C++ part

class MyClass {
  public: MyClass() { /** Constructor */ }
};

MyClass* staticObject;

extern "C" void CreateMyObjectInstance() {
   staticObject = new MyClass(); // constructor is called
} 

3 Comments

thanks to everyone, I hated to admit it but looks like there is no other way besides writing a wrapper.
Other option is to write managed c++ using compiler /crl flag. Then you can mix unmanaged and managed code in same dll and then simple call managed methods in your C# code. It will produce sam IL code as you would wrap native methods in your code. Quick intro codeproject.com/Articles/19354/…
The link is dead

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.