簡體   English   中英

是否可以使用C#DllImport從DLL導入非托管類或結構?

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

正如msdn http://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx所說“平台調用服務(PInvoke)允許托管代碼調用DLL中實現的非托管函數。 “

我想從我用c ++制作的DLL中導入一些類
有可能嗎?怎么樣?

例如,我在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;
};

哪種方式可以導入那些? 特別是那些帶指針的結構

您不需要編寫用於訪問的C ++托管代碼 - 但是 - 您無法輕松地在非托管內存和托管內存之間跳轉。 這里有幾個關鍵點1)使用[StructLayout(LayoutKind.Sequential)]來定義映射在c ++結構之上的.net類

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

2)像double,int32等基本類型有效地移動到P / Invoke層 - 更復雜的類型可以獲得thunking的.net變體 - msft doco覆蓋哪些數據類型有效移動,嘗試使用它們

3)C ++版本中指針的所有東西都是.net域中的IntPtr,如果你想要安全,你應該將它視為句柄,即你得到c ++方面對底層結構進行任何操作/訪問

4)訪問本機C ++非常簡單(Handle props是最初源自本機C ++端的IntPtrs)

[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)字符串和其他一些類型需要編組才能獲得.net可用的表單 - 請注意,當您將字符串傳遞給非托管代碼時,這會自動發生,但是當它處於入站代碼時您必須自己執行此操作

 [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); } } 

這是可能的....但您需要在C ++ / CLI中編寫包裝器代碼。 這允許您編寫可以從C#/ .net代碼中使用的類(在外部它是托管代碼),並且在實現中您可以使用C ++代碼。

您無法直接導入C ++類。 只有C風格的功能。 C風格的函數只允許您傳遞C基元類型,這使得它們易於互換。 通常,從非C ++代碼中,幾乎不可能正確傳遞C ++類型。 如果你不能傳入C ++對象,通常很少有你可以調用的有趣函數。

稍后編輯:或者,您可以為非托管功能編寫C風格的包裝函數。 您必須一次性傳遞所有參數(您可以傳遞結構),但您可以使用標准C / C ++編寫包裝器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM