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 CCGetAllDevsByArray(DevDataRecord *dda, int maxDevices);
#ifdef __cplusplus
}
#endif
struct __declspec(dllexport) 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 bootloaderversion[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_COUNT 100
DevDataRecord gDdr[MAX_DEVICE_COUNT];
...
memset(gDdr, 0, sizeof(gDdr) );
int devCount = CCGetAllDevsByArray(gDdr, MAX_DEVICE_COUNT);
/************************************************** *********/
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\ChipControl.dll", SetLastError = true)]
static extern bool CCInit();
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCStartScan();
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCStopScan();
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCGetAllDevsByArray([Out]out DevDataRecord ptr, int maxDevices);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct DevDataRecord
{
public UInt32 snr; // @field unsigned long
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string name; // @field char[256]
public int dhcp; // @field int
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string ip; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string netmask; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string gateway; // @field char[24]
public int signature; // @field int
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string targetname; // @field char[256]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string id; // @field char[24]
public int devindex; // @field int
public int devmhomeidx; // @field int
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string version; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string model; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string bootloaderversion; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string hwrevision; // @field char[24]
public int devicetype; // @field int
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 24)]
public string physicaladdress; // @field char[24]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
public string bname; // @field char[256]
public ulong bsnr; // @field unsigned long
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 24)]
public char[] bhwrevision; // @field char[24]
public int dataFlags; // @field int
};
#endregion
public const int MAX_DEVICE_COUNT = 100;
public DevDataRecord[] gDdr;
public Caller()
{
gDdr = new DevDataRecord[MAX_DEVICE_COUNT];
}
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 GetAllDevsByArray()
{
try
{
return CCGetAllDevsByArray(out gDdr[0], MAX_DEVICE_COUNT);
}
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 CCGetAllDevsByArray([Out]out DevDataRecord[] ptr, int maxDevices);
public int GetAllDevsByArray()
{
try
{
return CCGetAllDevsByArray(out gDdr, MAX_DEVICE_COUNT);
}
catch (Exception e)
{
return 0;
}
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCGetAllDevsByArray(ref DevDataRecord ptr, int maxDevices);
public int GetAllDevsByArray()
{
try
{
return CCGetAllDevsByArray(ref gDdr[0], MAX_DEVICE_COUNT);
}
catch (Exception e)
{
return 0;
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCGetAllDevsByArray(ref IntrPtr data, int maxDevices);
public int GetAllDevsByArray(int maxDevices)
{
try
{
unsafe
{
fixed (IntPtr ptr = gDdr)
{
return CCGetAllDevsByArray(ptr, maxDevices);
}
}
}
catch (Exception e)
{
return 0;
}
}
-------------------------------------------------------------------------------------
[DllImport(@"C:\Temp\ChipControl.dll", SetLastError = true)]
static extern int CCGetAllDevsByArray(ref Intptr data, int maxDevices);
public int GetAllDevsByArray(int maxDevices)
{
try
{
int arrayLen = gDdr.Length;
int structSize = Marshal.SizeOf(typeof(DevDataRecord));
IntPtr ptr = Marshal.AllocCoTaskMem(arrayLen * structSize);
for (int i = 0; i < arrayLen; i++)
{
Marshal.StructureToPtr(gDdr[i], (IntPtr)(ptr.ToInt32() + i * structSize), false);
}
int nrDevs = CCGetAllDevsByArray(ref ptr, maxDevices);
for (int i = 0; i < gDdr.Length; i++)
{
gDdr[i] = (DevDataRecord)Marshal.PtrToStructure(ptr, typeof(DevDataRecord));
ptr = (IntPtr)((int)ptr + Marshal.SizeOf(typeof(DevDataRecord)));
}
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