Reputation: 185
I have this C function:
void ECRYPT_keysetup(ECRYPT_ctx* ctx, const u8* key, u32 keysize, u32 ivsize);
that loads some key bytes to cipher context for example:
{0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0x12,0x34,0x56,0x78,0x9a,0xbc,0xde,0xf0}
I want to pass byte[]
from my .NET application to ECRYPT_keysetup
.
The problem is to marshall const u8*
. Any suggestions?
ECRYPT_ctx
is a structure:
u32 lfsr[1036];
u32 nfsr[1036];
u32 * nptr;
u32 * lptr;
u32 count;
const u8 * key;
u32 keysize;
u32 ivsize;
I have it's .NET representation:
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1036)]
public UInt32[] lfsr;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 1036)]
public UInt32[] nfsr;
public UIntPtr nptr;
public UIntPtr lptr;
public UInt32 count;
public byte[] key;
public UInt32 keysize;
public UInt32 ivsize;
May be my mistake is in structure declaration?
Upvotes: 2
Views: 574
Reputation: 18013
Solution 1
Map your types and use MarshalAs
attribute:
[DllImport("Mylib.dll")]
private static extern void ECRYPT_keysetup(
[In][MarshalAs(UnmanagedType.LPStruct)] ref ECRYPT_ctx ctx,
[In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)]byte[] key,
uint keysize,
uint ivsize);
// define whatever you have here (you can use Sequential layout without offsets, too)
[StructLayout(LayoutKind.Explicit)]
private struct ECRYPT_ctx
{
[FieldOffset(0)]
internal int someInt32;
[FieldOffset(4)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
internal byte[] someBytes;
}
Solution 2
Use pointers and marshal everything manually:
[DllImport("Mylib.dll")]
private static extern void ECRYPT_keysetup(IntPtr ctx, IntPtr key, uint keysize, uint ivsize);
In this case you should manage the allocations and disposal manually:
byte[] key = new byte[128]; // use the size you need, of course
IntPtr keyPtr = Marshal.AllocHGlobal(key.Length);
Marshal.Copy(key, 0, keyPtr, key.Length);
ECRYPT_ctx ctx = new ECRYPT_ctx();
IntPtr ctxPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ECRYPT_ctx)));
Marshal.StructureToPtr(ctx, ctxPtr, false);
ECRYPT_keysetup(ctxPtr, keyPtr, (uint)key.Length, ivsize);
Marshal.FreeHGlobal(keyPtr);
Marshal.DestroyStructure(ctxPtr, typeof(ECRYPT_ctx));
Marshal.FreeHGlobal(ctxPtr);
Remark: I considered all parameters as input ones. If you get something back in the buffers, define them as [In, Out]
, and in Solution 2 use the Marshal.PtrToStructure
method to convert the pointer to a managed structure.
Upvotes: 1