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.D efinePInvokeMet hod until I started implementing calls to
pointer (byref) parameters. The switch to TypeBuilder.Def inePInvokeMetho d
(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.Na me = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.Curre ntDomain.Define DynamicAssembly (assemblyName,
AssemblyBuilder Access.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder .DefineDynamicM odule("tempModu le");
// Dynamically construct a global PInvoke signature using the
input information
MethodBuilder methodBuilder =
moduleBuilder.D efinePInvokeMet hod(entryPointN ame,
dllName,
MethodAttribute s.Static | MethodAttribute s.Public |
MethodAttribute s.PinvokeImpl,
CallingConventi ons.Standard,
returnType,
parameterTypes,
CallingConventi on.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.S etImplementatio nFlags(MethodIm plAttributes.Pr eserveSig);
moduleBuilder.C reateGlobalFunc tions();
// Get a MethodInfo for the PInvoke method
MethodInfo methodInfo = moduleBuilder.G etMethod(entryP ointName);
Object returnValue = new Object();
try
{
returnValue = methodInfo.Invo ke(null, parameterValues );
MessageBox.Show (String.Format( "Value calculated: {0}",
Convert.ToDoubl e(returnValue). ToString()), entryPointName) ;
}
catch (Exception ex)
{
MessageBox.Show (ex.Message, entryPointName) ;
if (ex.InnerExcept ion != null)
MessageBox.Show (ex.InnerExcept ion.Message);
}
C# code using type builder follows (this doesn't
work)********** *************** *************** ***
AssemblyName assemblyName = new AssemblyName();
assemblyName.Na me = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.Curre ntDomain.Define DynamicAssembly (assemblyName,
AssemblyBuilder Access.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder .DefineDynamicM odule("tempModu le");
// Dynamically construct a global PInvoke signature using the
input information
TypeBuilder typeBuilder = moduleBuilder.D efineType("Temp Type");
MethodBuilder methodBuilder =
typeBuilder.Def inePInvokeMetho d(entryPointNam e,
dllName,
MethodAttribute s.Static | MethodAttribute s.Public |
MethodAttribute s.PinvokeImpl,
CallingConventi ons.Standard,
returnType,
parameterTypes,
CallingConventi on.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.S etImplementatio nFlags(MethodIm plAttributes.Pr eserveSig);
moduleBuilder.C reateGlobalFunc tions();
//...GetMethod returns nothing
MethodInfo methodInfo = moduleBuilder.G etMethod(entryP ointName);
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.I nvoke(null, parameterValues );
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.D efinePInvokeMet hod until I started implementing calls to
pointer (byref) parameters. The switch to TypeBuilder.Def inePInvokeMetho d
(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.Na me = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.Curre ntDomain.Define DynamicAssembly (assemblyName,
AssemblyBuilder Access.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder .DefineDynamicM odule("tempModu le");
// Dynamically construct a global PInvoke signature using the
input information
MethodBuilder methodBuilder =
moduleBuilder.D efinePInvokeMet hod(entryPointN ame,
dllName,
MethodAttribute s.Static | MethodAttribute s.Public |
MethodAttribute s.PinvokeImpl,
CallingConventi ons.Standard,
returnType,
parameterTypes,
CallingConventi on.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.S etImplementatio nFlags(MethodIm plAttributes.Pr eserveSig);
moduleBuilder.C reateGlobalFunc tions();
// Get a MethodInfo for the PInvoke method
MethodInfo methodInfo = moduleBuilder.G etMethod(entryP ointName);
Object returnValue = new Object();
try
{
returnValue = methodInfo.Invo ke(null, parameterValues );
MessageBox.Show (String.Format( "Value calculated: {0}",
Convert.ToDoubl e(returnValue). ToString()), entryPointName) ;
}
catch (Exception ex)
{
MessageBox.Show (ex.Message, entryPointName) ;
if (ex.InnerExcept ion != null)
MessageBox.Show (ex.InnerExcept ion.Message);
}
C# code using type builder follows (this doesn't
work)********** *************** *************** ***
AssemblyName assemblyName = new AssemblyName();
assemblyName.Na me = "tempDll";
AssemblyBuilder assemblyBuilder =
AppDomain.Curre ntDomain.Define DynamicAssembly (assemblyName,
AssemblyBuilder Access.Run);
ModuleBuilder moduleBuilder =
assemblyBuilder .DefineDynamicM odule("tempModu le");
// Dynamically construct a global PInvoke signature using the
input information
TypeBuilder typeBuilder = moduleBuilder.D efineType("Temp Type");
MethodBuilder methodBuilder =
typeBuilder.Def inePInvokeMetho d(entryPointNam e,
dllName,
MethodAttribute s.Static | MethodAttribute s.Public |
MethodAttribute s.PinvokeImpl,
CallingConventi ons.Standard,
returnType,
parameterTypes,
CallingConventi on.Winapi,
CharSet.Ansi);
// This global method is now complete
methodBuilder.S etImplementatio nFlags(MethodIm plAttributes.Pr eserveSig);
moduleBuilder.C reateGlobalFunc tions();
//...GetMethod returns nothing
MethodInfo methodInfo = moduleBuilder.G etMethod(entryP ointName);
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.I nvoke(null, parameterValues );