Hi
I need to call various functions in a native C++ DLL (FORTRAN eventually
too) - passing integers, doubles, (pointers and arrays to both of these as
well) and ultimately structures too. I was quite happily proceeding using
ModuleBuilder.DefinePInvokeMethod until I started implementing calls to
pointer (byref) parameters. The switch to TypeBuilder.DefinePInvokeMethod
(the one with the required custom modifiers) has resulted in the message
"the invoked member is not supported in a dynamic module".
Please could someone step me through the required calls in order to create a
totally dynamic call to such a DLL using the above approach. I don't really
want to save temporary assemblies to disk, but will if that is what it
required.
The sample below shows the module builder approach (which works) and then
the switch to the type builder approach which I am having problems with
(note: uses simple form of the method). The C++ function being called is
declared as follows:
extern "C"
{
__declspec( dllexport ) double WINAPI AddTwoDoubles2(double a, double b)
{
return a+b;
}
}
Thanks for any help anyone can provide.
Marek
C# code using module builder follows (this works
fine)*******************************************
Type returnType = typeof(double);
//...Set up the parameters:
Type[] parameterTypes = new Type[2];
object[] parameterValues = new object[2];
parameterTypes[0] = typeof(double);
parameterValues[0] = 2;
parameterTypes[1] = typeof(double);
parameterValues[1] = 2;
// Create a dynamic assembly and a dynamic module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(asse mblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder.DefineDynamicModule("tempModule");
// Dynamically construct a global PInvoke signature using the
input information
MethodBuilder methodBuilder =
moduleBuilder.DefinePInvokeMethod(entryPointName,
dllName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
returnType,
parameterTypes,
CallingConvention.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.SetImplementationFlags(MethodImplAtt ributes.PreserveSig);
moduleBuilder.CreateGlobalFunctions();
// Get a MethodInfo for the PInvoke method
MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);
Object returnValue = new Object();
try
{
returnValue = methodInfo.Invoke(null, parameterValues);
MessageBox.Show(String.Format("Value calculated: {0}",
Convert.ToDouble(returnValue).ToString()), entryPointName);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, entryPointName);
if (ex.InnerException != null)
MessageBox.Show(ex.InnerException.Message);
}
C# code using type builder follows (this doesn't
work)*******************************************
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(asse mblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder.DefineDynamicModule("tempModule");
// Dynamically construct a global PInvoke signature using the
input information
TypeBuilder typeBuilder = moduleBuilder.DefineType("TempType");
MethodBuilder methodBuilder =
typeBuilder.DefinePInvokeMethod(entryPointName,
dllName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
returnType,
parameterTypes,
CallingConvention.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.SetImplementationFlags(MethodImplAtt ributes.PreserveSig);
moduleBuilder.CreateGlobalFunctions();
//...GetMethod returns nothing
MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);
Object returnValue = new Object();
try
{
// Calling method builder directly results in the exception
"The invoked member is not supported in a dynamic module"
returnValue = methodBuilder.Invoke(null, parameterValues);