Известно, что в .Net Compact Framework не реализован метод Marshal.GetFunctionPointerForDelegate. Это создаёт достаточно большие проблемы при интеропе. В связи с вышесказанным была написана небольшая DLL. Она не является абсолютно универсальным решением, но покрывает подавляющее большинство случаев.
bifrost.cpp
/******************************************************************************/
/* */
/* _ ___ _..-._ */
/* \`.|\..----...-'` `-._.-'' _.-..' */
/* / ' ` , __.-'' */
/* )/` _/ \ `-_, / */
/* `-'" `"\_ ,_.-;_.-\_ ', NABU Project */
/* _.-'_./ {_.' ; / Bifrost Library */
/* {_.-``-' {_/ Copyright © 2005-2009, TrifleSoft */
/* */
/******************************************************************************/
#include <windows.h>
//
typedef DWORD (__stdcall * StdCall0)();
typedef DWORD (__stdcall * StdCall1)(DWORD arg1);
typedef DWORD (__stdcall * StdCall2)(DWORD arg1, DWORD arg2);
typedef DWORD (__stdcall * StdCall3)(DWORD arg1, DWORD arg2, DWORD arg3);
typedef DWORD (__stdcall * StdCall4)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4);
typedef DWORD (__stdcall * StdCall5)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5);
typedef DWORD (__stdcall * StdCall6)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6);
typedef DWORD (__stdcall * StdCall7)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7);
typedef DWORD (__stdcall * StdCall8)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8);
typedef DWORD (__stdcall * StdCall9)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9);
typedef DWORD (__stdcall * StdCallA)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA);
typedef DWORD (__stdcall * StdCallB)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB);
typedef DWORD (__stdcall * StdCallC)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC);
typedef DWORD (__stdcall * StdCallD)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD);
typedef DWORD (__stdcall * StdCallE)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD, DWORD argE);
typedef DWORD (__stdcall * StdCallF)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD, DWORD argE, DWORD argF);
//
typedef DWORD (__cdecl * CDecl0)();
typedef DWORD (__cdecl * CDecl1)(DWORD arg1);
typedef DWORD (__cdecl * CDecl2)(DWORD arg1, DWORD arg2);
typedef DWORD (__cdecl * CDecl3)(DWORD arg1, DWORD arg2, DWORD arg3);
typedef DWORD (__cdecl * CDecl4)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4);
typedef DWORD (__cdecl * CDecl5)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5);
typedef DWORD (__cdecl * CDecl6)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6);
typedef DWORD (__cdecl * CDecl7)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7);
typedef DWORD (__cdecl * CDecl8)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8);
typedef DWORD (__cdecl * CDecl9)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9);
typedef DWORD (__cdecl * CDeclA)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA);
typedef DWORD (__cdecl * CDeclB)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB);
typedef DWORD (__cdecl * CDeclC)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC);
typedef DWORD (__cdecl * CDeclD)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD);
typedef DWORD (__cdecl * CDeclE)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD, DWORD argE);
typedef DWORD (__cdecl * CDeclF)(DWORD arg1, DWORD arg2, DWORD arg3, DWORD arg4, DWORD arg5, DWORD arg6, DWORD arg7, DWORD arg8, DWORD arg9, DWORD argA, DWORD argB, DWORD argC, DWORD argD, DWORD argE, DWORD argF);
//
DWORD __stdcall CallUnmanagedFunctionPointer(
BOOL isCDecl,
LPVOID lpFunction,
DWORD argCount,
LPDWORD lpArgs)
{
if (isCDecl)
{
switch (argCount)
{
case 0x0: return ((CDecl0)lpFunction)();
case 0x1: return ((CDecl1)lpFunction)(lpArgs[0]);
case 0x2: return ((CDecl2)lpFunction)(lpArgs[0], lpArgs[1]);
case 0x3: return ((CDecl3)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2]);
case 0x4: return ((CDecl4)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3]);
case 0x5: return ((CDecl5)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4]);
case 0x6: return ((CDecl6)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5]);
case 0x7: return ((CDecl7)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6]);
case 0x8: return ((CDecl8)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7]);
case 0x9: return ((CDecl9)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8]);
case 0xA: return ((CDeclA)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9]);
case 0xB: return ((CDeclB)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10]);
case 0xC: return ((CDeclC)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11]);
case 0xD: return ((CDeclD)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12]);
case 0xE: return ((CDeclE)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12], lpArgs[13]);
case 0xF: return ((CDeclF)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12], lpArgs[13], lpArgs[14]);
}
}
else
{
switch (argCount)
{
case 0x0: return ((StdCall0)lpFunction)();
case 0x1: return ((StdCall1)lpFunction)(lpArgs[0]);
case 0x2: return ((StdCall2)lpFunction)(lpArgs[0], lpArgs[1]);
case 0x3: return ((StdCall3)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2]);
case 0x4: return ((StdCall4)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3]);
case 0x5: return ((StdCall5)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4]);
case 0x6: return ((StdCall6)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5]);
case 0x7: return ((StdCall7)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6]);
case 0x8: return ((StdCall8)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7]);
case 0x9: return ((StdCall9)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8]);
case 0xA: return ((StdCallA)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9]);
case 0xB: return ((StdCallB)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10]);
case 0xC: return ((StdCallC)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11]);
case 0xD: return ((StdCallD)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12]);
case 0xE: return ((StdCallE)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12], lpArgs[13]);
case 0xF: return ((StdCallF)lpFunction)(lpArgs[0], lpArgs[1], lpArgs[2], lpArgs[3], lpArgs[4], lpArgs[5], lpArgs[6], lpArgs[7], lpArgs[8], lpArgs[9], lpArgs[10], lpArgs[11], lpArgs[12], lpArgs[13], lpArgs[14]);
}
}
return 0xDEADBEAF;
}
/******************************************************************************/
/* END OF FILE */
/******************************************************************************/
bifrost.def
LIBRARY "Bifrost"
EXPORTS CallUnmanagedFunctionPointer
NativeMethods.cs
internal static class NativeMethods
{
[DllImport("bifrost.dll")]
public static extern IntPtr CallUnmanagedFunctionPointer(
[In][MarshalAs(UnmanagedType.Bool)] bool isCDecl,
[In] IntPtr lpFunction,
[In] int argCount,
[In][MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] IntPtr[] args);
}
MarshalCF.cs
public static class MarshalCF
{
private static IntPtr GetIntPtr(object value)
{
switch (value.GetType().FullName)
{
case "System.Char":
return new IntPtr((int)(char)value);
case "System.Int8":
return new IntPtr((sbyte)value);
case "System.UInt8":
return new IntPtr((int)(byte)value);
case "System.Int16":
return new IntPtr((short)value);
case "System.UInt16":
return new IntPtr((int)(ushort)value);
case "System.Int32":
return new IntPtr((int)value);
case "System.UInt32":
return new IntPtr((long)(uint)value);
case "System.Int64":
return new IntPtr((long)value);
case "System.UInt64":
return new IntPtr((long)(ulong)value);
case "System.IntPtr":
return (IntPtr)value;
case "System.UIntPtr":
return new IntPtr((long)((UIntPtr)value).ToUInt64());
}
throw new ArgumentException("value");
}
public static IntPtr CallUnmanagedCDeclFunction(
IntPtr lpFunction,
params object[] arguments)
{
IntPtr[] args = new IntPtr[arguments.Length];
for (int index = 0; index < args.Length; ++index)
{
args[index] = GetIntPtr(arguments[index]);
}
return
NativeMethods.CallUnmanagedFunctionPointer(
true,
lpFunction,
args.Length,
args);
}
public static IntPtr CallUnmanagedStdCallFunction(
IntPtr lpFunction,
params object[] arguments)
{
IntPtr[] args = new IntPtr[arguments.Length];
for (int index = 0; index < args.Length; ++index)
{
args[index] = GetIntPtr(arguments[index]);
}
return
NativeMethods.CallUnmanagedFunctionPointer(
false,
lpFunction,
args.Length,
args);
}
}
Здравствуйте, adontz, Вы писали:
A>Известно, что в .Net Compact Framework не реализован метод Marshal.GetFunctionPointerForDelegate.
А Emit подерживаеся в .Net Compact Framework?
Если да, то вот чисто managed реализация (написана для .NET v1), должна работать и в CF :
ps: есть правда некоторые ограничения, в частности не реализован user-marshaling,
за ненадобностью
, но при желании можно добавить
/// <summary>
/// Summary description for DelegateHelper.
/// </summary>
internal static class DelegateHelper
{
private const string InvokerAssemblyPrefix = "UnmanagedCodeInvokerAssembly_";
private const string InvokerTypePostfix = "_UnmanagedCodeInvoker";
private const string FuncPointerFieldName = "_funcPointer";
private const string FuncPointerParamName = "aFuncPointer";
private const string InvokeMethodName = "Invoke";
private static readonly Type DelegateType = typeof(Delegate);
private static readonly ConstructorInfo ObjectCtorInfo = typeof(object).GetConstructor(new Type[0]);
private static readonly object StaticSyncRoot = new object();
private static int _asmNum = 0;
private static AssemblyBuilder _asmBuilder = null;
private static ModuleBuilder _modBuilder = null;
/// <summary>
/// key: type of delegate; value: type of generated unmanaged invoker.
/// </summary>
private static Hashtable GeneratedTypes = new Hashtable();
/// <summary>
/// key: type of delegate; value: <see cref="DelegateInfo"/>.
/// </summary>
private static Hashtable CachedTypesToGenerate = new Hashtable();
private class DelegateInfo
{
public readonly Type DelegateType;
public readonly CallingConvention CallConv;
public DelegateInfo(Type aDelegateType, CallingConvention aCallConv)
{
DelegateType = aDelegateType;
CallConv = aCallConv;
}
}
public static bool PersistGeneratedCode
{
get
{
#if DEBUG
return true;
#else
return false;
#endif // DEBUG
}
}
private static MethodInfo GetInvokeMethodInfo(Type aDelegateType)
{
MethodInfo mi = aDelegateType.GetMethod(InvokeMethodName,
BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
return mi;
}
private static string GetInvokerTypeName(Type aDelegateType, int aTypeNum)
{
return aDelegateType.Name + InvokerTypePostfix + aTypeNum.ToString();
}
private static int GetNextAssemblyNumber()
{
return _asmNum++;
}
private static AssemblyName GenerateAssemblyName()
{
AssemblyName theAsmName = new AssemblyName();
theAsmName.Name = InvokerAssemblyPrefix +
AppDomain.CurrentDomain.GetHashCode().ToString() + "_" + GetNextAssemblyNumber();
return theAsmName;
}
public static void PreCompile(params Type[] aDelegateTypes)
{
PreCompile(false, aDelegateTypes);
}
public static void PreCompile(bool aCompileImmediately, params Type[] aDelegateTypes)
{
PreCompile(aCompileImmediately, CallingConvention.StdCall, aDelegateTypes);
}
public static void PreCompile(CallingConvention aCallConv, params Type[] aDelegateTypes)
{
PreCompile(false, aCallConv, aDelegateTypes);
}
public static void PreCompile(bool aCompileImmediately, CallingConvention aCallConv, params Type[] aDelegateTypes)
{
if (aDelegateTypes == null)
{
throw new ArgumentNullException("aDelegateTypes");
}
lock (StaticSyncRoot)
{
foreach (Type t in aDelegateTypes)
{
if (t == null)
{
throw new ArgumentNullException("aDelegateTypes", "At least one type is null.");
}
if (!DelegateType.IsAssignableFrom(t))
{
throw new ArgumentException("At least one type not derived from System.Delegate.", "aDelegateTypes");
}
if (t.IsAbstract)
{
throw new ArgumentException("At least one type is abstract.", "aDelegateTypes");
}
if (GeneratedTypes.Contains(t))
{
//already generated
continue;
}
if (CachedTypesToGenerate.Contains(t))
{
//already cached to generate
continue;
}
CachedTypesToGenerate.Add(t, new DelegateInfo(t, aCallConv));
}
if (CachedTypesToGenerate.Count > 0 && aCompileImmediately)
{
GenerateFromCache();
}
}
}
public static void Compile()
{
GenerateFromCache();
}
private static void GenerateFromCache()
{
lock (StaticSyncRoot)
{
if (CachedTypesToGenerate.Count == 0)
{
return;
}
if (_asmBuilder == null)
{
AssemblyName theAsmName = GenerateAssemblyName();
AssemblyBuilder theAsmBuilder = null;
if (PersistGeneratedCode)
{
string dir = Path.GetDirectoryName(new Uri(Assembly.GetEntryAssembly().Location).AbsolutePath);
theAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(theAsmName,
AssemblyBuilderAccess.RunAndSave, dir);
}
else
{
theAsmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(theAsmName,
AssemblyBuilderAccess.Run);
}
ModuleBuilder theModBuilder = theAsmBuilder.DefineDynamicModule(theAsmName.Name + ".dll");
_asmBuilder = theAsmBuilder;
_modBuilder = theModBuilder;
}
int theTypeNum = 0;
foreach (DelegateInfo theDelInfo in CachedTypesToGenerate.Values)
{
if (GeneratedTypes.Contains(theDelInfo.DelegateType))
{
continue;
}
theTypeNum = GeneratedTypes.Count;
Type theInvokerType = GenerateInvokerType(_modBuilder, theDelInfo.DelegateType,
theDelInfo.CallConv, theTypeNum);
GeneratedTypes.Add(theDelInfo.DelegateType, theInvokerType);
}
CachedTypesToGenerate.Clear();
if (PersistGeneratedCode)
{
//NOTE: после сохранения сборки ее нельзя модифицировать
_asmBuilder.Save(_modBuilder.Name);
_asmBuilder = null;
_modBuilder = null;
}
}
}
private static Type GenerateInvokerType(ModuleBuilder aModBuilder, Type aDelegateType,
CallingConvention aCallConv, int aTypeNum)
{
//create helper invoker class, which look like:
// class UnmanagedCodeInvoker
// {
// private IntPtr _funcPointer;
//
// public UnmanagedCodeInvoker(IntPtr aFuncPointer)
// {
// _funcPointer = aFuncPointer;
// }
//
// public RETVALUE Invoke(ARGUMENTS)
// {
// return _funcPointer(ARGUMENTS);
// }
// }
string theTypeName = GetInvokerTypeName(aDelegateType, aTypeNum);
TypeBuilder theTypeBuilder = aModBuilder.DefineType(theTypeName,
TypeAttributes.Sealed | TypeAttributes.NotPublic);
//create instance field which will be hold ref to function ptr
FieldBuilder theFieldBuilder = theTypeBuilder.DefineField(FuncPointerFieldName, typeof(IntPtr), FieldAttributes.Private);
//create ctor with one parameter: function ptr
ConstructorBuilder theCtorBuilder = theTypeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] {typeof(IntPtr)});
theCtorBuilder.DefineParameter(1, ParameterAttributes.In, FuncPointerParamName);
ILGenerator theCtorGen = theCtorBuilder.GetILGenerator();
//NOTE: Ldarg_0 contains "this", Ldarg_1 input parameter: function ptr
//call base ctor
theCtorGen.Emit(OpCodes.Ldarg_0);
theCtorGen.Emit(OpCodes.Call, ObjectCtorInfo);
//remember input function ptr in the instance field
theCtorGen.Emit(OpCodes.Ldarg_0);
theCtorGen.Emit(OpCodes.Ldarg_1);
theCtorGen.Emit(OpCodes.Stfld, theFieldBuilder);
theCtorGen.Emit(OpCodes.Ret);
MethodInfo theMethodPrototype = GetInvokeMethodInfo(aDelegateType);
//extract return type
Type theRetType = theMethodPrototype.ReturnType;
//extract parameters info
ParameterInfo[] theParamsInfo = theMethodPrototype.GetParameters();
Type[] theParamsType = new Type[theParamsInfo.Length];
for (int i = 0; i < theParamsInfo.Length; i++)
{
ParameterInfo theParamInfo = theParamsInfo[i];
theParamsType[i] = theParamInfo.ParameterType;
}
//create invoker method
MethodBuilder theInvokeMethodBuilder = theTypeBuilder.DefineMethod(InvokeMethodName,
MethodAttributes.Public, theRetType, theParamsType);
//todo: define marshal attributes
//note:
//in .NET 1.1 more difficult get\set this information,
//in .NEt v2 we can use MarshalAs attribute for get\set this information
//code look like:
//theInvokeMethodBuilder.SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(UnmanagedType.LPWStr));
//for (int i = 0; i < theParamsInfo.Length; i++)
//{
// ParameterInfo theParamInfo = theParamsInfo[i];
// ParameterBuilder theParamBuilder = theInvokeMethodBuilder.DefineParameter(i + 1, theParamInfo.Attributes, theParamInfo.Name);
// if ((theParamInfo.Attributes & ParameterAttributes.HasFieldMarshal) == ParameterAttributes.HasFieldMarshal)
// {
// //code look like:
// //theParamBuilder.SetMarshal(UnmanagedMarshal.DefineUnmanagedMarshal(UnmanagedType.LPWStr));
// }
//}
ILGenerator theInvokeMethodGen = theInvokeMethodBuilder.GetILGenerator();
//load parameters
for (int i = 0; i < theParamsInfo.Length; i++)
{
//ParameterInfo theParamInfo = theParamsInfo[i];
theInvokeMethodGen.Emit(OpCodes.Ldarg_S, (byte) (i + 1));
}
//load unmanaged function ptr
theInvokeMethodGen.Emit(OpCodes.Ldarg_0);
theInvokeMethodGen.Emit(OpCodes.Ldfld, theFieldBuilder);
//call unmanaged function
theInvokeMethodGen.EmitCalli(OpCodes.Calli, aCallConv, theRetType, theParamsType);
theInvokeMethodGen.Emit(OpCodes.Ret);
return theTypeBuilder.CreateType();
}
private static Type GetOrCreateInvokerType(Type aDelegateType, CallingConvention aCallConv)
{
Type theInvokerType = (Type) GeneratedTypes[aDelegateType];
if (theInvokerType == null)
{
lock (StaticSyncRoot)
{
theInvokerType = (Type) GeneratedTypes[aDelegateType];
if (theInvokerType == null)
{
if (!CachedTypesToGenerate.Contains(aDelegateType))
{
CachedTypesToGenerate.Add(aDelegateType, new DelegateInfo(aDelegateType, aCallConv));
}
GenerateFromCache();
theInvokerType = (Type) GeneratedTypes[aDelegateType];
}
}
}
return theInvokerType;
}
public static Delegate GetDelegateForFunctionPointer(IntPtr aFuncPtr, Type aDelegateType)
{
return GetDelegateForFunctionPointer(aFuncPtr, aDelegateType, CallingConvention.StdCall);
}
public static Delegate GetDelegateForFunctionPointer(IntPtr aFuncPtr,
Type aDelegateType, CallingConvention aCallConv)
{
if (aFuncPtr == IntPtr.Zero)
{
throw new ArgumentNullException("aFuncPtr");
}
if (aDelegateType == null)
{
throw new ArgumentNullException("aDelegateType");
}
if (!DelegateType.IsAssignableFrom(aDelegateType))
{
throw new ArgumentException("Type must be derived from System.Delegate.", "aDelegateType");
}
Type theInvokerType = GetOrCreateInvokerType(aDelegateType, aCallConv);
object theInvoker = Activator.CreateInstance(theInvokerType, new object[] {aFuncPtr});
return Delegate.CreateDelegate(aDelegateType, theInvoker, InvokeMethodName);
}
}