I did some test interaction functions from C# DLL into my C++ engine structure that lets the natie side create and manage those data while the managed side has read/write access to it so it is possible to pass for example an arrays native pointer from managed side to the native side for operating.
My Array.cs class looks like this
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace Bridge
{
public interface IArrayInternal
{
IntPtr Handle { get; set; }
Allocator.IAllocator GetAllocator();
int GetLength();
object GetValue(int index);
void SetValue(int index, object value);
/// <summary>
/// Resizes this array. Any data inside might get lost in order
/// ti achieve the targeted size
/// </summary>
void Resize(int size);
void Dispose();
}
public class ByteArrayInternal : Interopt.NativeMngClass, IArrayInternal
{
public new IntPtr Handle
{
get { return ptr; }
set { ptr = value; }
}
public virtual int GetLength()
{
if (ptr == IntPtr.Zero) return -1;
else return (int)csGetArraySizeByte(ptr);
}
public ByteArrayInternal(IntPtr ptr, Allocator.IAllocator allocator = null)
: base(ptr, allocator, true)
{ }
public ByteArrayInternal(UInt32 size, Allocator.IAllocator allocator = null)
: base(IntPtr.Zero, allocator, true)
{
if((ptr = csCreateArrayByte(GetAllocator().Handle)) != IntPtr.Zero)
csArrayResizeByte(ptr, size);
}
public object GetValue(int index)
{
if (ptr == IntPtr.Zero) return 0;
else return csGetArrayValueByte(ptr, (UInt32)index);
}
public void SetValue(int index, object value)
{
if (ptr != IntPtr.Zero)
csSetArrayValueByte(ptr, (UInt32)index, (byte)value);
}
public virtual void Resize(int size)
{
if (ptr == IntPtr.Zero) return;
else csArrayResizeByte(ptr, (UInt32)size);
}
public override void Dispose()
{
if (ptr != IntPtr.Zero) csDeleteArrayByte(ptr);
ptr = IntPtr.Zero;
Unregister();
}
[DllImport("CSharp.dll", EntryPoint = "csCreateArrayByte", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr csCreateArrayByte(IntPtr allocator);
[DllImport("CSharp.dll", EntryPoint = "csGetArraySizeByte", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 csGetArraySizeByte(IntPtr instance);
[DllImport("CSharp.dll", EntryPoint = "csGetArrayValueByte", CallingConvention = CallingConvention.Cdecl)]
private static extern byte csGetArrayValueByte(IntPtr instance, UInt32 index);
[DllImport("CSharp.dll", EntryPoint = "csSetArrayValueByte", CallingConvention = CallingConvention.Cdecl)]
private static extern void csSetArrayValueByte(IntPtr instance, UInt32 index, byte value);
[DllImport("CSharp.dll", EntryPoint = "csArrayResizeByte", CallingConvention = CallingConvention.Cdecl)]
private static extern void csArrayResizeByte(IntPtr instance, UInt32 size);
[DllImport("CSharp.dll", EntryPoint = "csDeleteArrayByte", CallingConvention = CallingConvention.Cdecl)]
private static extern void csDeleteArrayByte(IntPtr instance);
}
public class Array<T> : Interopt.INativeClass, Interopt.INativeMngClass, IDisposable
{
protected IArrayInternal handler;
public IntPtr Handle
{
get
{
if (handler == null) return IntPtr.Zero;
else return handler.Handle;
}
protected set
{
if (handler == null) return;
else handler.Handle = value;
}
}
public Allocator.IAllocator GetAllocator()
{
if (handler == null) return null;
else return handler.GetAllocator();
}
public virtual int Length
{
get
{
if (handler == null) return 0;
else return handler.GetLength();
}
}
public Array()
{ }
public Array(IntPtr ptr, Allocator.IAllocator allocator = null)
{
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Byte: handler = new ByteArrayInternal(ptr, allocator); break;
default: throw new ArgumentOutOfRangeException();
}
}
public Array(UInt32 size, Allocator.IAllocator allocator = null)
{
switch (Type.GetTypeCode(typeof(T)))
{
case TypeCode.Byte: handler = new ByteArrayInternal(size, allocator); break;
default: throw new ArgumentOutOfRangeException();
}
}
~Array()
{
Dispose();
}
public T this[int index]
{
get
{
return (T)Convert.ChangeType(handler.GetValue(index), typeof(T));
}
set
{
if (handler != null)
handler.SetValue(index, value);
}
}
public virtual void Resize(int size)
{
if(handler != null)
handler.Resize(size);
}
public virtual void Dispose()
{
if (handler != null)
handler.Dispose();
}
public override string ToString()
{
return string.Format("{0}[{1}]", typeof(T).Name, Length);
}
}
}
Used this schema for having some of my C# tools to access engine native functions