简体   繁体   中英

Is it possible to import unmanaged class or struct from DLL using C# DllImport?

As msdn http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx says "Platform Invocation Services (PInvoke) allows managed code to call unmanaged functions that are implemented in a DLL."

I want to import some class from DLL that i made in c++
Is it possible and how?

for example, i have some structures inside DLL:

struct __declspec(dllexport) DLLVector3
{
    float x, y, z;
};

struct __declspec(dllexport) DLLQuaternion
{
    float x, y, z, w;
};

class __declspec(dllexport) DLLCharacter
{
public:
    DLLVector3 position;
    DLLQuaternion orientation;

    DLLCharacter()
    {

    }

    ~DLLCharacter()
    {

    }

    void setPosition(PxVec3 pos)
    {
        position.x = pos.x;
        position.y = pos.y;
        position.z = pos.z;
    }

    void setOrientation(PxQuat or)
    {
        orientation.x = or.x;
        orientation.y = or.y;
        orientation.z = or.z;
        orientation.w = or.w;
    }
};

struct __declspec(dllexport) PhysicalObject
{
    DLLCharacter *character;
    PxRigidActor *mActor;
    PxController *mController;
};

Which way i can import those? Especially those structures with pointers

You don't need to write C++ managed code for access - but - you can't easily hop around between unmanaged and managed memory. Here's a few key points 1) Use [StructLayout(LayoutKind.Sequential)] to define .net classes that map on top of your c++ structs

 [StructLayout(LayoutKind.Sequential)] [Serializable] public struct SFVec3F : IRawStreamIO { public double _x; public double _y; public double _z; } 

2) Basic types like doubles, int32, etc move across the P/Invoke layer efficiently - more complex types earn you the .net variant of thunking - msft doco covers which data types move efficiently, try and use them

3) Everything that's a pointer in C++ land is an IntPtr in .net land and if you want to be safe you should treat it as a handle, ie you get the c++ side to do any manipulations/access to the underlying structure

4) Access to the native C++ is pretty straightforward (the Handle props are IntPtrs that were originally sourced on the native C++ side)

[DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern void AddChild(IntPtr csoPtr, IntPtr childPtr, short recomputeBounds, short adjustCoords, short blindchild);
public void AddChild(V3CSO theChild)
{
    AddChild(m_handle, theChild.Handle,0,0,0);
}

5) Strings and some other types require marshalling to obtain a .net usable form - note that this happens automatically for strings when you pass a string to unmanaged code, but you have to do it yourself when it's inbound

 [DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern IntPtr GetName(IntPtr csoPtr);
[DllImport("CS2V3.dll", CharSet = CharSet.Ansi)]
private static extern void SetName(IntPtr csoPtr, string newName);
  public string Name { get { IntPtr np = GetName(m_handle); return Marshal.PtrToStringAnsi(np); } set { SetName(m_handle, value); } } 

This is possible.... but you need to write wrapper code in C++/CLI. This allows you to write classes that can be used from C#/.net code (on the outside it is managed code), and in the implementation you can use C++ code.

You can't import the C++ classes directly. Only C-style functions. C-style functions only allow you to pass C primitive types, which makes interopping with them easy. In general, from non-C++ code, it is close to impossible to correctly pass in C++ types. And if you can't pass in C++ objects, there are typically very few interesting functions that you can call.

Later edit: Alternatively, you can write a C-style wrapper function for your unmanaged functionality. You will have to pass all parameters in one go (you can pass structs), but you can write the wrapper in standard C/C++.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM