如何在Delphi中使用DLL和.cs文件

本文关键字:DLL cs 文件 Delphi | 更新日期: 2023-09-27 18:28:39

我有一个用C++编写的DLL(帮助文件中这样说)我有一个包含函数名的.cs文件,看起来像这样:

    *// -------------- 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中的任何函数。这是Delphi代码:

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函数。我想知道有没有人有这方面的经验?如果有任何帮助,我将不胜感激

这个问题有些混乱。有大量的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

如何在Delphi中使用DLL和.cs文件