Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

using C DLL in C# code : error - Cannot marshal 'parameter #2': Intern

Status
Not open for further replies.

alaindoe

Programmer
May 17, 2011
2
0
0
BE
I have to use a dll written in C in a C# VS project.

I have some difficulties to translate and use the structures declared in C.

structure of the trend list :
===============================

C structure
-------------

typedef struct
{
WV_PARAMETER_ID WvParameterID [WV_MAX_TREND_PARAMETERS]; ;
TCHAR Label [WV_MAX_TREND_PARAMETERS] [WV_LABEL_SIZE] ;
int NumberOfTrends;
} WV_TREND_LIST ;

WV_MAX_TREND_PARAMETERS = 60
WV_LABEL_SIZE = 20



The problem I have is that there is only one returned value for the "NumberOfTrends" but 60 for the others. Then I found that I need to create the structures as follow.

This is working.


C# Structure
-------------

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_TREND_LIST
{
public WV_TREND_LIST_Items WV_TrendItem;
public int NumberOfTrends;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_TREND_LIST_Items
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 60, ArraySubType = System.Runtime.InteropServices.UnmanagedType.I4)]
public int[] WV_Trend_ParameterID;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 60, ArraySubType = System.Runtime.InteropServices.UnmanagedType.ByValTStr)]
public WV_ParameterLabel[] labelparameter;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_ParameterLabel
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string ParamLabel;
}



I have a to declare another set of structures that are about the same. The difference is that there is a lot of more data to be returned - too much I think. I got the following error when I call the procedure.

{"Cannot marshal 'parameter #2': Internal limitation: structure is too complex or too large."}

Structure for the trend values
===============================

C structure
-------------

typedef struct
{
WV_PARAMETER_ID WvParameterID ; // parameter id
TCHAR Label [WV_LABEL_SIZE] ; // label in english
WV_NET_UNITS_OF_MEASURE Units ;
TCHAR Values [WV_MAX_TREND_SAMPLES][WV_VALUE_SIZE];
} WV_TREND_PARAMETER_DATA;

WV_MAX_TREND_SAMPLES = 1501
WV_LABEL_SIZE = 20
WV_VALUE_SIZE = 20


C# Structure
-------------

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_TREND_DATA
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 60, ArraySubType = System.Runtime.InteropServices.UnmanagedType.Struct)]
public WV_TREND_PARAMETER_DATA[] WV_TrendDataItem;
//public Tren_DATA_Item_Class[] WV_TrendDataItem;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_TREND_PARAMETER_DATA
{
[MarshalAs(UnmanagedType.I4)]
public int Trend_Parameter_ID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string Trend_Label;
[MarshalAs(UnmanagedType.I4)]
public int Trend_Units;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1501, ArraySubType = System.Runtime.InteropServices.UnmanagedType.ByValTStr)]
public WV_TrendValue[] Trend_Values;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct WV_TrendValue
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)]
public string TrendValue;
}


DLL Declarations

[DllImport("WVAPI.dll", EntryPoint = "WvGetTrendData", SetLastError = true,

CharSet = CharSet.Ansi, ExactSpelling = true,

CallingConvention = CallingConvention.StdCall)]

[DllImport("WVAPI.dll", EntryPoint = "WvGetTrendData", SetLastError = true,

CharSet = CharSet.Ansi, ExactSpelling = true,

CallingConvention = CallingConvention.StdCall)]

public static extern int WvGetTrendData(int connectionID, ref structures.WV_TREND_DATA pTrendDatas, int numHours, structures.WV_TREND_LIST pTrends);

[DllImport("WVAPI.dll", EntryPoint = "WVGetAvailableTrends", SetLastError = true,

CharSet = CharSet.Ansi, ExactSpelling = true,

CallingConvention = CallingConvention.StdCall)]

public static extern int WVGetAvailableTrends(int pConnectID, ref structures.WV_TREND_LIST ptrendlist);

Variables declarations

structures.WV_TREND_LIST TrendList = new structures.WV_TREND_LIST();

structures.WV_TREND_DATA DataOfTheTrends = new structures.WV_TREND_DATA();

procedures

int returnTrendList = NATIVE_WV.WVGetAvailableTrends(connectionID, ref TrendList);

int returnTrendData = NATIVE_WV.WvGetTrendData(connectionID, ref DataOfTheTrends, totalhours, TrendList);

I have found on the internet that the solution of the error can be to use class instead of structures.

I must say that I have some difficulties to figure out how to fill a class with dynamic arrays. I can understand the mechanism with the structures : read sequentially the memory marshalling the values etc ... but for the class ?

Is there somebody that can help ?

best regards


 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top