Hi,
I want to use an unmanaged dll in C# .net and I'm having some troubles witch a function that should return an array. I'm new at this, so I don't know what I'm doing wrong.
Here is some code:
#define USERINT_FUNC __cdecl
#ifdef __cplusplus
extern "C" {
#endif
bool __cdecl CCInit();
int __cdecl CCStartScan();
int __cdeclC CCStopScan();
int __cdecl CCGetAllDevsByA rray(DevDataRec ord *dda, int maxDevices);
#ifdef __cplusplus
}
#endif
struct __declspec(dlle xport) DevDataRecord
{
unsigned long snr; // @field unsigned long
char name[256]; // @field char[256]
int dhcp; // @field int
char ip[24]; // @field char[24]
char netmask[24]; // @field char[24]
char gateway[24]; // @field char[24]
int signature; // @field int
char targetname[256]; // @field char[256]
char id[24]; // @field char[24]
int devindex; // @field int
int devmhomeidx; // @field int
char version[24]; // @field char[24]
char model[24]; // @field char[24]
char bootloaderversi on[24]; // @field char[24]
char hwrevision[24]; // @field char[24]
int devicetype; // @field int
char physicaladdress[24]; // @field char[24]
char bname[256]; // @field char[256]
unsigned long bsnr; // @field unsigned long
char bhwrevision[24]; // @field cahr[24]
int dataFlags; // @field int
};
/*************** *************** *************** **************/
This is some test code in Microsoft Visual C++ 6.0. This works fine. The function returns the right devCount and the gDdr array is filled correctly.
#define MAX_DEVICE_COUN T 100
DevDataRecord gDdr[MAX_DEVICE_COUN T];
...
memset(gDdr, 0, sizeof(gDdr) );
int devCount = CCGetAllDevsByA rray(gDdr, MAX_DEVICE_COUN T);
/*************** *************** *************** **************/
Then I started a C# console application in visual studio 2008. I made a Class that calls the functions from the unmannaged dll.
class Caller
{
#region Dll Imports
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern bool CCInit();
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCStartScan();
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCStopScan();
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCGetAllDevsByA rray([Out]out DevDataRecord ptr, int maxDevices);
[StructLayout(La youtKind.Sequen tial, CharSet = CharSet.Ansi)]
public struct DevDataRecord
{
public UInt32 snr; // @field unsigned long
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 256)]
public string name; // @field char[256]
public int dhcp; // @field int
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string ip; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string netmask; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string gateway; // @field char[24]
public int signature; // @field int
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 256)]
public string targetname; // @field char[256]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string id; // @field char[24]
public int devindex; // @field int
public int devmhomeidx; // @field int
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string version; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string model; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string bootloaderversi on; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string hwrevision; // @field char[24]
public int devicetype; // @field int
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 24)]
public string physicaladdress ; // @field char[24]
[MarshalAs(Unman agedType.ByValT Str, SizeConst = 256)]
public string bname; // @field char[256]
public ulong bsnr; // @field unsigned long
[MarshalAs(Unman agedType.ByValA rray, SizeConst = 24)]
public char[] bhwrevision; // @field char[24]
public int dataFlags; // @field int
};
#endregion
public const int MAX_DEVICE_COUN T = 100;
public DevDataRecord[] gDdr;
public Caller()
{
gDdr = new DevDataRecord[MAX_DEVICE_COUN T];
}
public void Init()
{
CCInit();
}
public void StartScan()
{
CCStartScan();
}
public void StopScan()
{
CCStopScan();
}
When I call the function like following, it returns the correct integer, but only the first element of the array is filled. This is the only way to get some result.
public int GetAllDevsByArr ay()
{
try
{
return CCGetAllDevsByA rray(out gDdr[0], MAX_DEVICE_COUN T);
}
catch (Exception e)
{
return 0;
}
}
}
I've tried a lot of other ways that I found in several forums or sites, but none of them work.
Here are some of the other ways:
-----------------------------------------------------------------------------------
static extern int CCGetAllDevsByA rray([Out]out DevDataRecord[] ptr, int maxDevices);
public int GetAllDevsByArr ay()
{
try
{
return CCGetAllDevsByA rray(out gDdr, MAX_DEVICE_COUN T);
}
catch (Exception e)
{
return 0;
}
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCGetAllDevsByA rray(ref DevDataRecord ptr, int maxDevices);
public int GetAllDevsByArr ay()
{
try
{
return CCGetAllDevsByA rray(ref gDdr[0], MAX_DEVICE_COUN T);
}
catch (Exception e)
{
return 0;
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCGetAllDevsByA rray(ref IntrPtr data, int maxDevices);
public int GetAllDevsByArr ay(int maxDevices)
{
try
{
unsafe
{
fixed (IntPtr ptr = gDdr)
{
return CCGetAllDevsByA rray(ptr, maxDevices);
}
}
}
catch (Exception e)
{
return 0;
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\ Temp\ChipContro l.dll", SetLastError = true)]
static extern int CCGetAllDevsByA rray(ref Intptr data, int maxDevices);
public int GetAllDevsByArr ay(int maxDevices)
{
try
{
int arrayLen = gDdr.Length;
int structSize = Marshal.SizeOf( typeof(DevDataR ecord));
IntPtr ptr = Marshal.AllocCo TaskMem(arrayLe n * structSize);
for (int i = 0; i < arrayLen; i++)
{
Marshal.Structu reToPtr(gDdr[i], (IntPtr)(ptr.To Int32() + i * structSize), false);
}
int nrDevs = CCGetAllDevsByA rray(ref ptr, maxDevices);
for (int i = 0; i < gDdr.Length; i++)
{
gDdr[i] = (DevDataRecord) Marshal.PtrToSt ructure(ptr, typeof(DevDataR ecord));
ptr = (IntPtr)((int)p tr + Marshal.SizeOf( typeof(DevDataR ecord)));
}
return nrDevs;
}
catch (Exception e)
{
return 0;
}
}
Is there someone who can help me and tell me what I'm doing wrong?
Many thanks,
Elke