Marshaling er Pinvoke Headache - c#

I cannot seem to pass the right arguments correctly. I get
"Invalid Name Parsing buffer size" error
Lotus notes function in dname.h
STATUS LNPUBLIC DNParse(
DWORD Flags,
const char far *TemplateName,
const char far *InName,
DN_COMPONENTS far *Comp,
WORD CompSize);
structure below
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DN_COMPONENTS
{
public int Flags;
[MarshalAs(UnmanagedType.LPWStr)]
public string C;
public short OLength;
[MarshalAs(UnmanagedType.LPWStr)]
public string O;
[MarshalAs(UnmanagedType.LPWStr)]
public string CN;
};
c#
Below is what I have tried
Status sts = 0;
StringBuilder szServer = new StringBuilder(names.MAXUSERNAME);
string notUsedString = null;
DWORD notUsed = 0;
dname.DN_COMPONENTS xdDC = new DN_COMPONENTS();
sts = nnotesDLL.SECKFMGetUserName(szServer);
//IntPtr structPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(dname.DN_COMPONENTS)));
//UInt16 num = Convert.ToUInt16(Marshal.SizeOf(structPtr));
//WORD num = Convert.ToUInt16(Marshal.SizeOf(structPtr));
int num = Marshal.SizeOf(typeof(DN_COMPONENTS));
IntPtr structPtr = Marshal.AllocCoTaskMem(num);
sts = nnotesDLL.DNParse(notUsed, notUsedString, szServer, structPtr, (UInt32)num);
this.xdDC = (dname.DN_COMPONENTS)Marshal.PtrToStructure(structPtr, typeof(dname.DN_COMPONENTS));
xdDC.CN = Decode(Marshal.ReadIntPtr(structPtr), ushort.MaxValue);
///CN=SomeFirstName SomeLastName/OU=Corp/O=test
I am looking for "SomeFirstName SomeLastName"
[DllImport("nnotes.DLL", CallingConvention = CallingConvention.StdCall)]
public unsafe static extern Status DNParse(DWORD notUsed, string notUsedString, StringBuilder InName, IntPtr structPtr, UInt32 structPtrSizeOf);
I have tried all variations by ref to all, ref to struct, changed to string, int, uint Nothing!!!
Help...
What I am looking for is CN=SomeFirstName SomeLastName/OU=Corp/O=test

The problems that I can see:
You did not declare all the fields in the struct.
It is unlikely that the struct is packed. Remove the Pack setting.
You need to declare the pointers in the struct as IntPtr. The marshaller cannot marshal them from native to managed. Declare them as IntPtr and use Marshal.PtrToStringAnsi to convert.

Related

C# marshaling C++ functions

I am trying to use the Hikvision SDK https://www.hikvision.com/en/support/download/sdk/
My current goal is to open the door (trigger an output) with the intercom outdoor station.
I managed to do the login (NET_DVR_LoginV40) and display the outdoor station's camera feed.
My next step would be to open the door. For this I need to call the NET_DVR_RemoteControl function passing in among others the struct of NET_DVR_Control_GateWay.
Now when doing this it does not work it returns error 17 which is apparently:
Parameter error. Input or output parameters in the SDK API is NULL, or
the value or format of the parameters does not match with the
requirement.
So it is practically 100% that something is iffy in my C# code. But I have no idea what it is and as far as I know this is quite impossible to pinpoint easily if you are not an expert at this (I am not)
The dll import for the function:
[DllImport(#"..\bin\HCNetSDK.dll")]
public static extern bool NET_DVR_RemoteControl(int lUserID, uint dwCommand, IntPtr lpInBuffer, uint dwInBufferSize);
The struct for the parameter of the previous function:
[StructLayoutAttribute(LayoutKind.Sequential)]
public struct NET_DVR_Control_GateWay
{
public uint dwSize;
public uint dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public UInt16 wLockID;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 32, ArraySubType = UnmanagedType.I1)]
public byte[] byControlSrc;
public byte byControlType;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 3, ArraySubType = UnmanagedType.I1)]
public byte[] byRes3;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 16, ArraySubType = UnmanagedType.I1)]
public byte[] byPassword;
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 108, ArraySubType = UnmanagedType.I1)]
public byte[] byRes2;
public void Init()
{
byRes3 = new byte[64];
byRes2 = new byte[108];
}
}
My method for the door opening:
private void button_Door1_Click(object sender, EventArgs e)
{
CHCNetSDK.NET_DVR_Control_GateWay gateWay = new CHCNetSDK.NET_DVR_Control_GateWay();
gateWay.Init();
gateWay.dwSize = (uint)Marshal.SizeOf(gateWay);
gateWay.dwGatewayIndex = 1;
gateWay.byCommand =1; //opening command
gateWay.byLockType = 0 ; //this is a normal lock not a smart lock
gateWay.wLockID = 0; //this is 0 because I want to use the door station's output
gateWay.byControlSrc = new byte[] {123} ; // this needs to be something, but doesn't matter what
gateWay.byControlType = 1 ; //this needs to be 1 or 2 but does not matter which
//gateWay.byPassword = ; this is not needed because the LockType is 0
IntPtr ptrStruData = Marshal.AllocHGlobal((int)gateWay.dwSize);
var dd = CHCNetSDK.NET_DVR_RemoteControl(lUserID, 16009, ptrStruData, gateWay.dwSize);
MessageBox.Show(dd.ToString() + CHCNetSDK.NET_DVR_GetLastError().ToString() + "\n" + gateWay.dwSize.ToString() + "\n" + "ptrStruData:" + ptrStruData.ToString());
}
According to the documentation the function looks like this
And the struct is defined as such
So according to my knowledge I have done the definition and import correctly.
I would appreciate if someone could set me in the right direction as I have never worked with C#, c++ interoperation before and at this point I have no idea how to go forward, how could I debug, how could I determine the problem in my code.
I have tried contacting the manufacturer about this issue, but they cannot help directly with my code, and from their perspective everything is working as it should as I get back the error that it is me who is the cause for the issue.
Your help is much appreciated!
You allocate some memory with Marshal.AllocHGlobal, you do not copy your gateWay structure into that memory, you pass the pointer to the allocated memory to NET_DVR_RemoteControl so that it sees random garbage, and then you do not free the allocated memory so that it leaks.
You could have fixed it by copying gateWay into the allocated memory and then freeing it after the call.
Instead, however, it is better to let the marshaller do its job:
[DllImport(HIKVISION_LIBRARY, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = false)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool NET_DVR_RemoteControl(int lUserID, int dwCommand, [In] ref NET_DVR_CONTROL_GATEWAY lpInBuffer, int dwInBufferSize);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)]
public struct NET_DVR_CONTROL_GATEWAY
{
public int dwSize;
public int dwGatewayIndex;
public byte byCommand;
public byte byLockType;
public short wLockID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NAME_LEN)]
public string byControlSrc;
public byte byControlType;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] byRes3;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PASSWD_LEN)]
public string byPassword;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 108)]
public byte[] byRes2;
}
var gateWay = new NET_DVR_CONTROL_GATEWAY()
{
dwSize = Marshal.SizeOf<NET_DVR_CONTROL_GATEWAY>(),
dwGatewayIndex = 1,
byCommand = 1,
byLockType = 0,
wLockID = 0,
byControlType = 1
};
var dd = NET_DVR_RemoteControl(lUserID, 16009, ref gateWay, gateWay.dwSize);

how to pass a pointer to C# struct to a method in C

I want to use a c++ dll in c#. I'm using [DllImport] to call the method. I'm having trouble passing struct to a method.
I have a C struct:
typedef struct
{
DWORD TopPoint;
DWORD EndPoint;
WORD dwCount;
MYFUNC_NUMERIC11 *pGetData;
} MYFUNC_BUFFERNORMAL;
MYFUNC_NYMERIC11 is another struct.
typedef struct
{
BYTE Sign; // Sign ("±")
BYTE Integer[3]; // 3-digit integer (no zero suppression)
BYTE Period; // Decimal point (".")
BYTE Decimal[6]; // 6-digit decimal number
} MYFUNC_NUMERIC11;
I have written a C# struct to mimic this.
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public unsafe struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
A pointer to the struct is an argument in a method. C# function is:
[DllImport("MYFUNC_DLL.dll", EntryPoint = "MYFUNC_GetData", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall, ThrowOnUnmappableChar = true)]
public static extern int MYFUNC_GetData(IntPtr myfuncHandle, UInt32 dwIO, ref IntPtr pBufferNormal, Byte bccFlg);
This is the method in C:
MYFUNC_STATUS MYFUNC_GetData(MYFUNC_HANDLE myfuncHandle, DWORD dwOut, MYFUNC_BUFFERNORMAL *pBufferNormal , BYTE bccFlg)
The return type is cast to an enum, which has an interpretation. The struct parameter is invalid. I've tried to allocate memory using Marshal.AllocHGlobal(...), but the parameter is still invalid, i.e. there is no error during compilation but the value returned is incorrect.
I've spent quite a few hours on this, still unable to figure out what to do. A lot of similar questions exist already, like here: How do I convert c struct from dll to C# or here: How to pass C# array to C++ and return it back to C# with additional items?, but I, somehow, still haven't figured out a way.
Something like this should work, at least with one element in the array (is it an array?). For an array, you will have to allocate sizeof * count of elements and marshal (StructureToPtr) each element at its offset.
var num = new MYFUNC_NUMERIC11();
num.Integer = new byte[] { 1, 2, 3 };
num.Decimal = new byte[] { 4, 5, 6, 7, 8, 9 };
num.Sign = 10;
num.Period = 11;
var buffer = new MYFUNC_BUFFERNORMAL();
buffer.Count = 1234;
buffer.EndPoint = 5678;
buffer.TopPoint = 9;
buffer.pGetData = Marshal.AllocCoTaskMem(Marshal.SizeOf(num));
try
{
Marshal.StructureToPtr(num, buffer.pGetData, false);
MYFUNC_GetData(Whatever, 0, ref buffer, 0);
}
finally
{
Marshal.FreeCoTaskMem(buffer.pGetData);
}
With these definitions.
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_BUFFERNORMAL
{
public uint TopPoint;
public uint EndPoint;
public ushort Count;
public IntPtr pGetData;
}
[StructLayout(LayoutKind.Sequential)]
public struct MYFUNC_NUMERIC11
{
public byte Sign;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public byte[] Integer;
public byte Period;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public byte[] Decimal;
}
// check calling convention
[DllImport(#"MYFUNC_DLL.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern MYFUNC_STATUS MYFUNC_GetData(IntPtr myfuncHandle, uint dwIO, ref MYFUNC_BUFFERNORMAL pBufferNormal, byte bccFlg);

Pass C# Byte[] to C++ API

I have to pass an Byte array containing an MAC-Address to a C++ Method. Since I don't have much experience with working with c
C++ APIsI don't know how to do this. I've tried to pass the array itself, but got an invalid parameter code as response from the API. I've also tried to create an IntPtr but to no avail.
I know that the problem is that C++ can't handle managed datatypes such as arrays, so I've to create a unmanaged array somehow, I think.
Here is the definition of the C++ Method:
ll_status_t LL_Connect(
ll_intf_t intf,
uint8_t address[6]);
The array in C# is defined the following way:
Byte[] addr = new Byte[6];
Of course, the array is not empty.
For example:
C++
extern "C"
{
__declspec(dllexport) void GetData(uint8_t* data, uint32_t length)
{
for (size_t i = 0; i < length; ++i)
data[i] = i;
}
}
C#
[DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetData([In, Out] [MarshalAs(UnmanagedType.LPArray)] byte[] data, uint length);
And use in C#
byte[] data = new byte[4];
GetData(data, (unit)data.Lenght);
If you have an array fixed length, for example:
C++
extern "C"
{
__declspec(dllexport) void GetData(uint8_t data[6])
{
for (size_t i = 0; i < 6; ++i)
data[i] = i;
}
}
C#
[DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern void GetData([In, Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] data);
And use in C#
byte[] data = new byte[6];
GetData(data);
For your case:
[DllImport("LibName.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
public static extern int LL_Connect(byte intf, [In, Out] [MarshalAs(UnmanagedType.LPArray, SizeConst = 6)] byte[] address);

How to send the structure pointer to DeviceIoControl API in WINCE7 C#.net

I am working on WIN CE platform, developing windows forms in C#.Net.
The DeviceIoControl API is working fine with the parameters (mentioned below) in c++ console application.
PNIC_STATISTICS structure in nuiouser.h
global declarations :
TCHAR PCI1_NAME[] = _T("PCI\\ManiXX1");
TCHAR *AUB_NAME = NULL;
AUB_NAME = PCI1_NAME;
pNICStat = (PNIC_STATISTICS)malloc(sizeof(NIC_STATISTICS)) ;
pNICStat->ptcDeviceName = AUB_NAME ; //wchar_t* ptcDeviceName
DeviceIoControl( hUB94Port, //void*
IOCTL_NDISUIO_NIC_STATISTICS,
pNICStat, //PNIC_STATISTICS
0,
pNICStat, //PNIC_STATISTICS
sizeof(NIC_STATISTICS),
&dwReturnedBytes,
NULL
);
<==============================================================================>
But I'm getting problems in implementing the same with C#.Net CF for WIN-CE7
My WIN-CE Code is as follows:
Modified Structure in C#:
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Unicode)]
public struct __NIC_STAT
{
ulong Size; // Of this structure.
public Char[] ptcDeviceName; // The device name to be queried..
ulong DeviceState; // DEVICE_STATE_XXX above
ulong DeviceState; // DEVICE_STATE_XXX above
ulong MediaType; // NdisMediumXXX
ulong MediaState; // MEDIA_STATE_XXX above
ulong PhysicalMediaType;
ulong LinkSpeed; // In 100bits/s. 10Mb/s = 100000
UInt64 PacketsSent;
UInt64 PacketsReceived;
ulong InitTime; // In milliseconds
ulong ConnectTime; // In seconds
UInt64 BytesSent; // 0 - Unknown (or not supported)
UInt64 BytesReceived; // 0 - Unknown (or not supported)
UInt64 DirectedBytesReceived;
UInt64 DirectedPacketsReceived;
ulong PacketsReceiveErrors;
ulong PacketsSendErrors;
ulong ResetCount;
ulong MediaSenseConnectCount;
ulong MediaSenseDisconnectCount;
} ;
From this Structure I am just filling ptcDeviceName and trying to send.
__NIC_STAT NIC_STAT = new __NIC_STAT();
Char[] toBytes = {'P','C','I','\\','M','a','n','i','X','X','1','\0'}
NIC_STAT.ptcDeviceName = toBytes; //public Char[] ptcDeviceName; in structure
// __NIC_STAT this is the same structure as
//in nuiouser.h
int sz = Marshal.SizeOf(NIC_STAT.GetType());//sometimes Getting exception here
intptr ptr = Marshal.AllocHGlobal(sz);
Marshal.StructureToPtr((__NIC_STAT)NIC_STAT, ptr, false);
unsafe
{
DeviceIoControl(hFileHandle,
IOCTL_NDISUIO_NIC_STATISTICS,
ref ptr,
0,
ref ptr,
sz,
ref dwReturnedBytes,
0);
}//unsafe
It's corresponding prototype
[DllImport("coredll.dll", CharSet = CharSet.Auto, SetLastError = true)]
unsafe public static extern bool DeviceIoControl(
int hDevice,
int dwIoControlCode,
ref intptr InBuffer,
int nInBufferSize,
ref intptr OutBuffer,
int nOutputBufferSize,
ref int pBytesReturned,
int pOverlapped
);
In Win-CE DeviceIoControl() is getting failed, with exception and not displaying any error codes. and sometimes getting error code as 87 (INVALID PARAMETERS).
I feel ptcDeviceName is creating the problem or may be because of allocating memory for pointer (ptr) ?
In Console application we are sending ptcDeviceName as Wchar_t* but in WIN-CE so I used
public Char[] ptcDeviceName;
Can anybody tell me where I am doing wrong.?
You have a couple problems going on here.
First is that you seem to think a ulong is 32-bits in C#, but it's not. It'64 bits, so your struct is totally mapped wrong.
Second, I'm sure you need to be setting the struct Size member before passing it to the call.
Third, that ptcDeviceName member is a pointer to a wide character string. That means that in the struct itself it's 4 bytes. I'd likely make it an IntPtr. You then need to separately allocate the string, pin it, and put the pointer to it into that member slot. Since `StringToHGlobal doesn't exist in the CF, it would look something like this:
public struct __NIC_STAT
{
public uint Size;
public IntPtr ptcDeviceName;
public uint DeviceState;
public uint DeviceState;
public uint MediaType;
public uint MediaState;
public uint PhysicalMediaType;
public uint LinkSpeed;
public ulong PacketsSent;
public ulong PacketsReceived;
public uint InitTime;
public uint ConnectTime;
public ulong BytesSent;
public ulong BytesReceived;
public ulong DirectedBytesReceived;
public ulong DirectedPacketsReceived;
public uint PacketsReceiveErrors;
public uint PacketsSendErrors;
public uint ResetCount;
public uint MediaSenseConnectCount;
public uint MediaSenseDisconnectCount;
};
....
var myStruct = new __NIC_STAT();
myStruct.Size = (15 * 4) + (6 * 8);
var name = "PCI\\Manixx1\0";
var nameBytes = Encoding.Unicode.GetBytes(name);
myStruct.ptcDeviceName = Marshal.AllocHGlobal(nameBytes.Length);
try
{
Marshal.Copy(nameBytes, 0, myStruct.ptcDeviceName, nameBytes.Length);
// make the IOCTL call, a-la
NativeMethods.DeviceIoControl(...., ref myStruct, ....);
}
finally
{
Marshal.FreeHGlobal(myStruct.ptcDeviceName);
}

C# call C++ DLL passing pointer-to-pointer argument

Could you guys please help me solve the following issue?
I have a C++ function dll, and it will be called by another C# application.
One of the functions I needed is as follow:
struct DataStruct
{
unsigned char* data;
int len;
};
DLLAPI int API_ReadFile(const wchar_t* filename, DataStruct** outData);
I wrote the following code in C#:
class CS_DataStruct
{
public byte[] data;
public int len;
}
[DllImport("ReadFile.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
private static extern int API_ReadFile([MarshalAs(UnmanagedType.LPWStr)]string filename, ref CS_DataStruct data);
Unfortunately, the above code is not working... I guess that is due to the C++ func takes a pointer-to-pointer of DataStruct, while I just passed a reference of CS_DataStruct in.
May I know how can I pass a pointer-to-pointer to the C++ func? If it is not possible, is there any workaround? (the C++ API is fixed, so changing API to pointer is not possible)
Edit:
Memory of DataStruct will be allocated by c++ function. Before that, I have no idea how large the data array should be.
(Thanks for the comments below)
I used the following test implementation:
int API_ReadFile(const wchar_t* filename, DataStruct** outData)
{
*outData = new DataStruct();
(*outData)->data = (unsigned char*)_strdup("hello");
(*outData)->len = 5;
return 0;
}
void API_Free(DataStruct** pp)
{
free((*pp)->data);
delete *pp;
*pp = NULL;
}
The C# code to access those functions are as follows:
[StructLayout(LayoutKind.Sequential)]
struct DataStruct
{
public IntPtr data;
public int len;
};
[DllImport("ReadFile.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]
unsafe private static extern int API_ReadFile([MarshalAs(UnmanagedType.LPWStr)]string filename, DataStruct** outData);
[DllImport("ReadFile.dll", CallingConvention = CallingConvention.Cdecl)]
unsafe private static extern void API_Free(DataStruct** handle);
unsafe static int ReadFile(string filename, out byte[] buffer)
{
DataStruct* outData;
int result = API_ReadFile(filename, &outData);
buffer = new byte[outData->len];
Marshal.Copy((IntPtr)outData->data, buffer, 0, outData->len);
API_Free(&outData);
return result;
}
static void Main(string[] args)
{
byte[] buffer;
ReadFile("test.txt", out buffer);
foreach (byte ch in buffer)
{
Console.Write("{0} ", ch);
}
Console.Write("\n");
}
The data is now transferred to buffer safely, and there should be no memory leaks. I wish it would help.
It isn't necessary to use unsafe to pass a pointer to an array from a DLL. Here is an example (see the 'results' parameter). The key is to use the ref attribute. It also shows how to pass several other types of data.
As defined in C++/C:
#ifdef __cplusplus
extern "C" {
#endif
#ifdef BUILDING_DLL
#define DLLCALL __declspec(dllexport)
#else
#define DLLCALL __declspec(dllimport)
#endif
static const int DataLength = 10;
static const int StrLen = 16;
static const int MaxResults = 30;
enum Status { on = 0, off = 1 };
struct Result {
char name[StrLen]; //!< Up to StrLen-1 char null-terminated name
float location;
Status status;
};
/**
* Analyze Data
* #param data [in] array of doubles
* #param dataLength [in] number of floats in data
* #param weight [in]
* #param status [in] enum with data status
* #param results [out] array of MaxResults (pre-allocated) DLLResult structs.
* Up to MaxResults results will be returned.
* #param nResults [out] the actual number of results being returned.
*/
void DLLCALL __stdcall analyzeData(
const double *data, int dataLength, float weight, Status status, Result **results, int *nResults);
#ifdef __cplusplus
}
#endif
As used in C#:
private const int DataLength = 10;
private const int StrLen = 16;
private const int MaxThreatPeaks = 30;
public enum Status { on = 0, off = 1 };
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Result
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = StrLen)] public string name; //!< Up to StrLen-1 char null-terminated name
public float location;
public Status status;
}
[DllImport("dllname.dll", CallingConvention = CallingConvention.StdCall, EntryPoint = "analyzeData#32")] // "#32" is only used in the 32-bit version.
public static extern void analyzeData(
double[] data,
int dataLength,
float weight,
Status status,
[MarshalAs(UnmanagedType.LPArray, SizeConst = MaxResults)] ref Result[] results,
out int nResults
);
Without the extern "C" part, the C++ compiler would mangle the export name in a compiler dependent way. I noticed that the EntryPoint / Exported function name matches the function name exactly in a 64-bit DLL, but has an appended '#32' (the number may vary) when compiled into a 32-bit DLL. Run dumpbin /exports dllname.dll to find the exported name for sure. In some cases you may also need to use the DLLImport parameter ExactSpelling = true. Note that this function is declared __stdcall. If it were not specified, it would be __cdecl and you'd need CallingConvention.Cdecl.
Here is how it might be used in C#:
Status status = Status.on;
double[] data = { -0.034, -0.05, -0.039, -0.034, -0.057, -0.084, -0.105, -0.146, -0.174, -0.167};
Result[] results = new Result[MaxResults];
int nResults = -1; // just to see that it changes (input value is ignored)
analyzeData(data, DataLength, 1.0f, status, ref results, out nResults);
If you do call native code, make sure your structs are alligned in the memory. CLR does not guarantee alignment unless you push it.
Try
[StructLayout(LayoutKind.Explicit)]
struct DataStruct
{
string data;
int len;
};
More info:
http://www.developerfusion.com/article/84519/mastering-structs-in-c/

Categories