I need to pass a structure containing an array of structures that is of an unknown length at compile-time.
I've found examples of how to Marshal variable-size arrays of primitives with Marshal.Copy and fixed-size arrays of structures using an IntPtr[] array and Marshal.StructureToPtr, but that uses MarshalAs(UnamangedType.ByValArray) in the structure definition which requires the SizeConst parameter.
Here's a sample of what I'm trying to do. In the C dll I have a structure with a sine wave defintion
typedef struct sinWave
{
double amp; /* sine wave amplitude */
double t; /* time */
double period; /* oscilation period */
double omega; /* phase angle */
} sinWave;
and a structure that can hold multiple waves
typedef struct sinWaveAdd
{
sinWave *waves; /* array of sine waves */
int len; /* length of the array */
} sinWaveAdd;
This gets used in wave superposition function with the following prototype
__declspec( dllexport ) double calculateMult( sinWaveAdd *in )
In c# I have a sinWave struct that works well on its own
[StructLayout(LayoutKind.Sequential)]
public class sinWaveStruct
{
public double amp; /* sine wave amplitude */
public double t; /* time */
public double period; /* oscillation period */
public double omega; /* phase angle */
}
public sinWaveStruct(double ampP, double tP, double periodP, double omegaP)
{
amp = ampP;
t = tP;
period = periodP;
omega = omegaP;
}
}
but I don't really know how to construct the larger structure
[StructLayout(LayoutKind.Sequential)]
public class sinWaveAddClass
{
public IntPtr waves; /* array of sinWaveStruct waves */
public int len; /* length of array */
}
since I need the number of waves to not be constant.
Is there a way to Marshal the waves array to sinWaveStruct[], IntPtr, or IntPtr[] without having a constant size array?
I'd declare the structures as struct
. That makes them value types rather than reference types. Important when you want to make arrays of them. Especially as sinWave
is blittable.
public struct sinWaveStruct
{
public double amp; /* sine wave amplitude */
public double t; /* time */
public double period; /* oscillation period */
public double omega; /* phase angle */
}
public struct sinWaveAdd
{
public IntPtr waves; /* array of sinWaveStruct waves */
public int len; /* length of array */
}
The function you import is:
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern double calculateMult(ref sinWaveAdd in);
So then create and populate an array of sinWaveAdd
:
sinWaveStruct[] arr = new sinWaveStruct[len];
// populate arr
Then pin the array and obtain its address:
GCHandle arrHandle = GCHandle.Alloc(arr, GCHandleType.Pinned);
try
{
sinWaveAdd in;
in.waves = arrHandle.AddrOfPinnedObject();
in.len = len;
double retval = calculateMult(ref in);
}
finally
{
arrHandle.Free();
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.