Red Gate forums :: View topic - problem with struct array pointer
Return to www.red-gate.com RSS Feed Available

Search  | Usergroups |  Profile |  Messages |  Log in  Register 
Go to product documentation
PInvoke.Net
PInvoke.Net forum

problem with struct array pointer

Search in PInvoke.Net forum
Post new topic   Reply to topic
Jump to:  
Author Message
elke



Joined: 25 Mar 2009
Posts: 1

PostPosted: Wed Mar 25, 2009 9:37 am    Post subject: problem with struct array pointer Reply with quote

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]
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic All times are GMT + 1 Hour
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group