2011-04-03 162 views
0

如何從C#中調用以下方法,該方法位於C++ dll中?我如何在C#中重新創建以下結構?如何從C#代碼調用非託管dll中的函數?


原始

方法:

LONG MyMethod (P_HOLO_INFO pInfo, LPVOID pBuffer, LPUSHORT pTracksWritten); 

結構:該方法使用以下結構:

typedef struct _HOLO_INFO 
{ 
    LONG  lHoloType; 
    LONG  lStatus; 
    HANDLE lThreadHandle; 
    LONG  lErrorCode; 
    LONG  lDriveIndex; 
    LONG  lHeight; 
    SHORT iFormat; 
    INT  iStartingTrack; 
    LONG  lWrite; 
    LONG  lSkip; 
    BOOL  bSkipZero; 
    BOOL  bInvert; 
    LONG  lMaxConsecutiveErrors; 
    LONG  lMaxTotalErrors; 
    LONG  lMostConsecutiveErrors; 
    LONG  lTotalErrors; 
    LPBYTE pBuffer; 
    LPUSHORT pTracksWritten; 
    LONG  bUpsideDown; 
} HOLO_INFO, *P_HOLO_INFO; 

我曾在C#這樣

方法:

[DllImport("My.dll", EntryPoint = "[email protected]")] 
public unsafe static extern long MyMethod(ref HOLO_INFO pInfo, Byte[] pBuffer,ref ushort pTracksWritten); 

結構:

該方法使用以下結構:

unsafe public struct HOLO_INFO 
{ 
    public long lHoloType; 
    public long lStatus; 
    public long lThreadHandle; 
    public ulong lErrorCode; 
    public long lDriveIndex; 
    public long lHeight; 
    public short iFormat; 
    public int iStartingTrack; 
    public long lWrite; 
    public long lSkip; 
    public bool bSkipZero; 
    public bool bInvert; 
    public long lMaxConsecutiveErrors; 
    public long lMaxTotalErrors; 
    public long lMostConsecutiveErrors; 
    public long lTotalErrors; 
    public Byte* pBuffer; 
    public long* pTracksWritten; 
    public long bUpsideDown; 
}; 

我進行的呼叫以這樣的方法:

do 
    { 
    result = MyMethod(ref pInfo,ptrBuf,pTracksWritten); 
    } while (result ==1); 

因爲,它返回1,如果是有源 0,如果它成功完成 3,如果因爲錯誤而停止。如果方法處於運行狀態(Active-1),則爲 。它修改pInfopTracksWritten更新狀態信息。

+1

我不得不做類似的事情。我所做的就是將DLL包裝在CLRC++類中,並在一側獲得C++結構,並在另一側返回CLR兼容結構,但是這是一段時間後,現在可能有更好的方法。 – 2011-04-03 14:55:22

+0

你在這裏顯然是正確的。如果我是你,我會用C++編寫一個特殊的測試函數來消除細節。讓它將輸入寫入文件。然後您可以檢查您從C#發送的內容是否正確。對於任何其他方向的數據傳遞,請讓測試C#程序也登錄到文件。 – 2011-04-03 16:27:31

回答

0

Using a Very C# DLL in C++

你可以做一個「簡單」的把戲[這個答案(答案Using a Very C# DLL in C++),或者你可以看看茂盛的嵌入按照my answer

+0

我需要在C#中使用C++ dll。 – aWebdesigner09 2011-04-03 15:21:39

+0

我一定一直在睡覺。有一個VS插件將C proto +聲明翻譯成P/Invoke內容...如果我有時間,我會再次找到它 – sehe 2011-04-03 15:23:44

+0

@ aWebdesigner09:標題誤導,聽起來像是你想要的相反。我編輯它。 – ildjarn 2011-04-03 15:23:51

3

很多問題:

  • LONG應該在C#中聲明爲int
  • HANDLE是IntPtr。
  • pTracksWritten丟失。您可能需要製作它,而pBuffer,一個IntPtr並使用Marshal.AllocHGlobal爲它們分配內存。
  • 您需要[DllImport]聲明中的CallingConvention才能使用Cdecl。

如果您無法調試非託管代碼,那麼獲得這個工作的可能性並不是很大。一個基本的理智測試是確保元帥。SizeOf()在非託管代碼中返回與sizeof()相同的長度。接下來驗證在調試本機代碼時傳遞的參數看起來不錯。接下來,檢查本機代碼中的指針使用情況,並確認它們未被複制。

+0

如果可能,請提供完整的答案。我花了很多時間尋找和嘗試不同的方式。非常感謝您的快速反應。 – aWebdesigner09 2011-04-03 15:18:12

+2

我只是給你適當的口徑子彈。把槍指向你的腳是你得到的報酬。在C++/CLI中執行此操作將是明智的。 – 2011-04-03 15:19:16

+1

@ 12建議stdcall – 2011-04-03 16:09:36

0

這給一個鏡頭:

[DllImport("My.dll", EntryPoint = "[email protected]")] 
int MyMethod (HOLO_INFO pInfo, IntPtr pBuffer, IntPtr pTracksWritten); 

public class HOLO_INFO 
{ 
    public int lHoloType; 
    public int lStatus; 
    public IntPtr lThreadHandle; 
    public int lErrorCode; 
    public int lDriveIndex; 
    public int lHeight; 
    public short iFormat; 
    public int iStartingTrack; 
    public int lWrite; 
    public int lSkip; 
    public bool bSkipZero; 
    public bool bInvert; 
    public int lMaxConsecutiveErrors; 
    public int lMaxTotalErrors; 
    public int lMostConsecutiveErrors; 
    public int lTotalErrors; 
    public IntPtr pBuffer; 
    public IntPtr pTracksWritten; 
    public int bUpsideDown; 
} 

取決於他們是如何分配的,你可能需要使用Marshal.Copy訪問HOLO_INFO.pBufferMarshal.PtrToStructure訪問HOLO_INFO.pTracksWritten(或Marshal.Copy,如果它是一個數組與指針一個奇異的值)。

+0

調用約定將stdcall – 2011-04-03 16:22:35

+0

你肯定意味着:'int MyMethod(ref HOLO_INFO Info,IntPtr pBuffer,out UInt16 TracksWritten);' – 2011-04-03 16:25:25

+0

@David Heffernan:沒有。 'DllImport'的默認調用約定是stdcall,但VC++的默認值是cdecl(請參閱http://msdn.microsoft.com/en-us/library/46t77ak2.aspx)。關於'ref','HOLO_INFO'是一個'class',所以它已經通過引用傳遞;使用'ref'將會類似於C++中的'HOLO_INFO **'或'P_HOLO_INFO *'。關於'out ushort',在我看來'HOLO_INFO.pTracksWritten'可能最終會保存該指針值,如果沒有使用明確的堆分配,在函數返回後該指針值將無效。 – ildjarn 2011-04-03 16:29:41

相關問題