2015-12-31 121 views
0

我有一個DLL用C++編寫(幫助文件是這麼說的) 我有這個cs文件保存函數名和看起來像這樣一個cs文件:如何使用DLL和德爾福

*// -------------- Part of MXIO.cs File ----- 
//#define _NET_WINCE 
//========================================================================================== 
using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Runtime.InteropServices; 

namespace MOXA_CSharp_MXIO 
{ 
    class MXIO_CS 
    { 
     public const int SUPPORT_MAX_SLOT = 16; 
     public const int SUPPORT_MAX_CHANNEL = 64; 
     public const int SupportMaxChOfBit = SUPPORT_MAX_CHANNEL>>3; 
     // 
#if _NET_WINCE 
     [StructLayout(LayoutKind.Explicit, Size = 4)] 
#else 
     [StructLayout(LayoutKind.Explicit, Size = 4, Pack = 1)] 
#endif 

     //V1.2 OPC Tag DATA Struct 
#if _NET_WINCE 
     [StructLayout(LayoutKind.Sequential)] 
#else 
     [StructLayout(LayoutKind.Sequential, Pack = 1)] 
#endif 
     public struct _IOLOGIKSTRUCT 
     { 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 
      public byte[] BytMagic; 
      public UInt16 wVersion;   // struct define of version 1.0.0 
      public UInt16 wLength; 
      public UInt16 wHWID;   // for user to know which API to Read/write 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] 
      public byte[] dwSrcIP; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
      public byte[] BytSrcMAC; 
      public byte BytMsgType;   // for AP side to known what kind of Message return 
      public UInt16 wMsgSubType; 
      //------------------------ 
      // tag timestamp 
      public UInt16 wYear; 
      public byte BytMonth; 
      public byte BytDay; 
      public byte BytHour; 
      public byte BytMin; 
      public byte BytSec; 
      public UInt16 wMSec; 
      //------------------------- 
      public byte BytLastSlot;  //add to notice the last slot, Range 0-16, 0=>myself only 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT)] 
      public byte[] BytLastCh; 
      //------------------------- 
      // support up to 16 slots and 64 channels //size:5408 bytes 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT * SUPPORT_MAX_CHANNEL)] 
      public byte[] BytChType; // channel I/O type 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT)] 
      public UInt16[] wSlotID; // Slot Module ID 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT * SupportMaxChOfBit)] 
      public byte[] BytChNumber; // bitwised¡A1=Enable¡A0=Disable 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT * SUPPORT_MAX_CHANNEL)] // 
      public _ANALOG_VAL[] dwChValue; 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = SUPPORT_MAX_SLOT * SupportMaxChOfBit)] 
      public byte[] BytChLocked; // bitwised, 0=free, 1=locked 
     } 
     // 
#if _NET_WINCE 
     [StructLayout(LayoutKind.Sequential)] 
#else 
     [StructLayout(LayoutKind.Sequential, Pack = 1)] 
#endif 
     public struct _ACTDEV_IO 
     { 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
      public byte[] BytSrcMAC; 
      public Int32 iHandle; 
     } 
     // 
#if _NET_WINCE 
     [StructLayout(LayoutKind.Sequential)] 
#else 
    [StructLayout(LayoutKind.Sequential, Pack = 1)] 
#endif 
     public struct _MODULE_LIST 
     { 
      public UInt16 nModuleID; //Module ID of device 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
      public byte[] szModuleIP; //Save IP address of device 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
      public byte[] szMAC;  //Save MAC address of device 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] 
      public byte[] szModuleIP1; //Save 2nd IP address of device 
      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] 
      public byte[] szMAC1;  //Save 2nd MAC address of device 
      public byte bytLanUse;  //0 -> Lan0, 1 -> Lan1 
     } 

     public delegate void pfnCALLBACK(IntPtr bytData, UInt16 wSize); 

     public delegate void pfnTagDataCALLBACK(_IOLOGIKSTRUCT[] ios, UInt16[] wMutex); 

     /**********************************************/ 
     /*           */ 
     /*  Ethernet Module Connect Command  */ 
     /*           */ 
     /**********************************************/ 
     [DllImport("MXIO_NET.dll")] 
     public static extern int MXEIO_Init(); 

     [DllImport("MXIO_NET.dll")] 
     public static extern void MXEIO_Exit(); 

     [DllImport("MXIO_NET.dll")] 
     public static extern int MXEIO_Connect(byte[] szIP, UInt16 wPort, UInt32 dwTimeOut, Int32[] hConnection); 

     [DllImport("MXIO_NET.dll")] 
     public static extern int MXEIO_Disconnect(Int32 hConnection); 

     [DllImport("MXIO_NET.dll")] 
     public static extern int MXEIO_CheckConnection(Int32 hConnection, UInt32 dwTimeOut, byte[] bytStatus); 

     /***********************************************/ 
     /*            */ 
     /*    General Command    */ 
     /*            */ 
     /***********************************************/ 
     [DllImport("MXIO_NET.dll")] 
     public static extern int MXIO_GetDllVersion(); 

     [DllImport("MXIO_NET.dll")] 
     public static extern int MXIO_GetDllBuildDate(); 
     /*************************************************/ 
     /*            */ 
     /*     Error Code     */ 
     /*            */ 
     /*************************************************/ 
     public const int MXIO_OK = 0; 
     public const int ILLEGAL_FUNCTION = 1001; 
     public const int ILLEGAL_DATA_ADDRESS = 1002; 

     /*************************************************/ 
     /*            */ 
     /*    Data Format Setting    */ 
     /*            */ 
     /*************************************************/ 
     /* Data length define */ 
     public const int BIT_5 = 0x00; 
     public const int BIT_6 = 0x01; 
     public enum MXIO_ModuleDataIndex: int 
     { 
      //--------------------------------------------------------------------------- 
      MX_ML_MODULE_LIST_SIZE       = 47, 
      MX_ML_INDEX_WHWID        = 0, 
      MX_ML_INDEX_SZIP0        = 2, //SIZE:16 (STRING) 
      MX_ML_INDEX_SZMAC0        = 18, //SIZE:6 (STRING) 
      MX_ML_INDEX_SZIP1        = 24, //SIZE:16 (STRING) 
      MX_ML_INDEX_SZMAC1        = 40, //SIZE:6 (STRING) 
      MX_ML_INDEX_BYTLANUSE       = 46 
     }; 
     //--------------------------------------------------------------------------- 
    } 
}* 

我試圖訪問DLL中的任何函數。這裏是德爾福代碼:

type 
    TMyCall = function: integer; stdcall; 

const 
    MYDLL = 'D:\DelphiProjects\DLL_Read\MXIO_NET.dll'; 

procedure TForm2.btnFncClick(Sender: TObject); 
var 
    i,j,k: integer; 
    Handle: THandle; 
    mCall : TMyCall; 
begin 
    // Load the library 
    Handle := LoadLibrary(MYDLL); 

    // If succesful ... 
    if Handle <> 0 then 
    begin 
     // Assign function from the DLL to the 
     // function variable mCall 
     @mCall := GetProcAddress(Handle, 'MXIO_GetDllVersion'); 
     // If successful 
     if @mCall <> nil then 
     begin 
     Label3.Caption:= 'DLL version =' + IntToStr(mCall); 
     end 
     else 
     Label3.Caption:= 'Function Not found'; 

     // Unload library 
     FreeLibrary(Handle); 
    end 
    else 
    Label3.Caption:= 'Version Handle = 0'; 
end; 

問題:GetProcAddress失敗並返回nil。

我試圖將代碼切割成最小和完整的部分,希望我能做到這一點。現在我正在考慮將.cs文件(至少它的一部分)轉換成Delphi單元並從那裏調用DLL函數。我想知道有沒有人有過這方面的經驗?我想感謝所有幫助

+0

「DllImport」指令用於其他方向。看到[這個問題](http://stackoverflow.com/questions/4818850/is-is-possible-to-export-functions-from-ac-sharp-dll-like-in-vs-c)瞭解更多信息看起來你在這裏試圖做什麼。 –

+0

我相信這個編輯只會讓人更加困惑。在原始問題中,似乎他想從用C++編寫的abc.dll導入,並且他只有一個以.cs提供的DLLImport樣本,並在上面進行了重現。但是現在在這個編輯中,似乎他想知道他是否需要extern「C」聲明,如果他的DLL是由給他他已經有的源代碼的人寫的。如果他想從C#的dll進口翻譯,但他更瞭解C,那麼這是他的選擇。 HIS問題讓他感到困惑,而這種編輯並沒有多大幫助。 –

+1

請顯示真實密碼 –

回答

2

的問題是,有些困惑的.NET替代。有大量的C#代碼沒有相應的Delphi代碼。人們不禁要問,Delphi代碼是否真的顯示出你聲稱的問題。

無論如何,假設你所顯示的GetProcAddress調用確實失敗,那麼這個問題很容易回答。 GetProcAddress有兩種故障模式:

  1. 提供的模塊句柄無效。
  2. 提供的過程名稱無效。

我們可以排除第1項,因爲通過調用LoadLibrary來調用模塊句柄。如果LoadLibrary成功,那麼我們知道我們有一個有效的模塊句柄。

所以,唯一的結論是提供的過程名稱無效。這意味着您已加載的DLL不會導出名爲MXIO_GetDllVersion的函數。您可以在GetProcAddress返回nil後立即致電GetLastError來確認。當你這樣做時,你會得到值127這是ERROR_PROC_NOT_FOUND

您可以通過檢查DLL導出的函數名來確認這一點。使用諸如Dependency Walker之類的工具來執行此操作。

對你的Delphi代碼的一個其他小的評論。您已經使用THandle作爲模塊句柄,但這是錯誤的類型。它不會影響行爲,但它在語義上是錯誤的。使用HMODULE

+0

大衛,我的Delphi代碼只是一個測試代碼,看看我是否可以讀取DLL函數,我無法啓動真正的prg。我運行DependencyWalker並檢出輸出,我可以在下面的文本輸出中看到帶有下劃線的函數名(我讀過一篇文章,這是正常的,因爲C++ dll - 我嘗試了兩種可能性):[ C] 305(0x0131)304(0x0130)_MXIO_GetDllVersion @ 0 0x000601C0我想我會放棄,可能會嘗試學習c#。謝謝你的幫助,我很感激。 – cengo

+0

'_MXIO_GetDllVersion @ 0'是一個具有裝飾名稱的stdcall函數。 MS C++編譯器可能會在'extern「C''下使用'dllexport'導出。請注意,@ 0表示堆棧中參數的大小爲0,而@ 0是該函數名稱的一部分。現在你知道這個函數的名字了,你可以用'GetProcAddress(...,'_MXIO_GetDllVersion @ 0')來導入它。我認爲這個問題現在就完成了,對嗎? –

+0

謝謝。如果你願意,你可以接受答案:http://meta.stackexchange.com/q/5234/ –

-1
  1. 檢查,如果兩者是相同的字大小 - 64/32位
  2. 德爾福 - 你使用哪個版本?

對於低於舊DELPHIS規則(下面XE,但它可以是下面XE6我已經曾經試圖使用.NET的DLL但失敗)

  • 。網絡程序可以運行Delphi DLL(甚至32位)
  • Delphi程序無法運行.Net dll's。無論如何都有一些(微小的)例外,但通常它們不兼容。
  • 在這種情況下,真正的寫C++本地DLL或找到你的聲卡驅動
  • +1

    這不是一個答案 –