I have a DLL written in C++ (help file says so) I have this .cs file that holds the function names and looks something like this:
*// -------------- 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
};
//---------------------------------------------------------------------------
}
}*
I'm trying to access any of the functions inside the DLL. Here is the Delphi code:
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;
Problem: GetProcAddress
fails and returns nil.
I tried to cut the code into minimal and complete portion, hope I could do this time. Now I'm thinking to convert the .cs file (at least some part of it) into a Delphi unit and call the DLL functions from there. I wonder if anyone had experience on this? I'd appreciate any help