problem with struct array pointer

Announcements and discussion for PInvoke

Moderators: Luke Jefferson, Robert

problem with struct array pointer

Postby elke » Wed Mar 25, 2009 9:37 am

Hi,

I 'm new in using PInvoke. I want to use an unmanaged dll in C# .net and I'm having some troubles witch a function that should return an array.

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.

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 some who can help me and tell me what I'm doing wrong?
Many thanks,

Elke
[/b]
elke
 
Posts: 1
Joined: Wed Mar 25, 2009 9:16 am

Return to PInvoke.Net

Who is online

Users browsing this forum: No registered users and 1 guest