M
Marek
Hi
As well as trying to call a fortran dll with a structure parameter from a C#
front end, we are trying to do this using AssemblyBuilder and MethodInfo to
do it dynamically. Ultimately this will be done using a configuration file,
but in the first instance I am trying to do this using code. The FORTRAN
structure looks like this:
TYPE Type1
! Scalars plus fixed dimension arrays
SEQUENCE
INTEGER :: &
iScalar1
DOUBLE PRECISION, DIMENSION(iFixDim1,iFixDim2) :: &
dArray1, &
dArray2
DOUBLE PRECISION :: &
dScalar1
INTEGER, DIMENSION(iFixDim1) :: &
iArray1
INTEGER :: &
iScalar2
END TYPE Type1
and the entry point for the dll subroutine looks like this:
!
=====================================================================================
SUBROUTINE CreateType1 (iScalar1, dArray1, dArray2, dScalar1,
iArray1, &
iScalar2, rType)
!
=====================================================================================
!DEC$ ATTRIBUTES DLLEXPORT :: CreateType1
!
! Purpose
! -------
! Create a Type 1 structure
!
! Arguments
! ---------
INTEGER, INTENT(IN) :: &
iScalar1, &
iScalar2
DOUBLE PRECISION, DIMENSION(iFixDim1,iFixDim2), INTENT(IN) :: &
dArray1, &
dArray2
DOUBLE PRECISION, INTENT (IN) :: &
dScalar1
INTEGER, INTENT(IN), DIMENSION(iFixDim1) :: &
iArray1
TYPE(Type1), INTENT(OUT) :: &
rType
! Begin
! -----
rType%iScalar1 = iScalar1
rType%iScalar2 = iScalar2
rType%dScalar1 = dScalar1
rType%iArray1 = iArray1
rType%dArray1 = dArray1
rType%dArray2 = dArray2
RETURN
END SUBROUTINE CreateType1
*/
The C# (finally) looks like this:
string fileName = @"C:\Data\Visual Studio
2005\projects\CallingFortranStructures\CallingFortranStructures\recp.dll";
string entryPointName = "MDERECPRFTEST_mp_CREATETYPE1";
AssemblyBuilder dynamicAsm = null;
MethodInfo methodInfo = null;
Type[] parameterTypes = new Type[7];
parameterTypes[0] = typeof(int); //iScalar1
parameterTypes[0] = parameterTypes[0].MakeByRefType();
parameterTypes[1] = typeof(double[,]); //dArray1
parameterTypes[1] = parameterTypes[1].MakeByRefType();
parameterTypes[2] = typeof(double[,]); //dArray2
parameterTypes[2] = parameterTypes[2].MakeByRefType();
parameterTypes[3] = typeof(double); //dScalar1
parameterTypes[3] = parameterTypes[3].MakeByRefType();
parameterTypes[4] = typeof(int[]); //iArray1
parameterTypes[4] = parameterTypes[4].MakeByRefType();
parameterTypes[5] = typeof(int); //iScalar2
parameterTypes[5] = parameterTypes[5].MakeByRefType();
parameterTypes[6] = typeof(RTYPE1); //rType
parameterTypes[6] = parameterTypes[6].MakeByRefType();
// Create a dynamic assembly and a dynamic module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "CreateType1";
dynamicAsm =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
dynamicAsm.DefineDynamicModule("CreateType1");
// Dynamically construct a global PInvoke signature
// using the input information
MethodBuilder methodBuilder =
moduleBuilder.DefinePInvokeMethod(entryPointName,
fileName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
typeof(void),
parameterTypes,
CallingConvention.StdCall,
CharSet.Ansi);
methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
moduleBuilder.CreateGlobalFunctions();
// Get a MethodInfo for the PInvoke method and store it away for
later use:
methodInfo = moduleBuilder.GetMethod(entryPointName);
if (methodInfo != null)
{
//...Set up the parameters:
object[] parameterValues = new object[7];
//ParameterModifier parameterModifiers = new
ParameterModifier();
//...Set the parameter values ready for the call:
parameterValues[0] = 0;
parameterValues[1] = new double[5, 10];
parameterValues[2] = new double[5, 10];
parameterValues[3] = 0.0;
parameterValues[4] = new int[5];
parameterValues[5] = 0;
RTYPE1 rtype1 = new RTYPE1();
rtype1.iArray1 = new int[5];
rtype1.iScalar1 = 1;
rtype1.iScalar2 = 3;
rtype1.dArray1 = new double[5, 10];
rtype1.dArray2 = new double[5, 10];
rtype1.dScalar1 = 3.14;
parameterValues[6] = rtype1;
object returnValue = typeof(void);
returnValue = methodInfo.Invoke(null, parameterValues);
I appreciate that this is rather specific, but I was wondering whether
anyone could shed any light on this problem.
Thanks in advance.
Marek
As well as trying to call a fortran dll with a structure parameter from a C#
front end, we are trying to do this using AssemblyBuilder and MethodInfo to
do it dynamically. Ultimately this will be done using a configuration file,
but in the first instance I am trying to do this using code. The FORTRAN
structure looks like this:
TYPE Type1
! Scalars plus fixed dimension arrays
SEQUENCE
INTEGER :: &
iScalar1
DOUBLE PRECISION, DIMENSION(iFixDim1,iFixDim2) :: &
dArray1, &
dArray2
DOUBLE PRECISION :: &
dScalar1
INTEGER, DIMENSION(iFixDim1) :: &
iArray1
INTEGER :: &
iScalar2
END TYPE Type1
and the entry point for the dll subroutine looks like this:
!
=====================================================================================
SUBROUTINE CreateType1 (iScalar1, dArray1, dArray2, dScalar1,
iArray1, &
iScalar2, rType)
!
=====================================================================================
!DEC$ ATTRIBUTES DLLEXPORT :: CreateType1
!
! Purpose
! -------
! Create a Type 1 structure
!
! Arguments
! ---------
INTEGER, INTENT(IN) :: &
iScalar1, &
iScalar2
DOUBLE PRECISION, DIMENSION(iFixDim1,iFixDim2), INTENT(IN) :: &
dArray1, &
dArray2
DOUBLE PRECISION, INTENT (IN) :: &
dScalar1
INTEGER, INTENT(IN), DIMENSION(iFixDim1) :: &
iArray1
TYPE(Type1), INTENT(OUT) :: &
rType
! Begin
! -----
rType%iScalar1 = iScalar1
rType%iScalar2 = iScalar2
rType%dScalar1 = dScalar1
rType%iArray1 = iArray1
rType%dArray1 = dArray1
rType%dArray2 = dArray2
RETURN
END SUBROUTINE CreateType1
*/
The C# (finally) looks like this:
string fileName = @"C:\Data\Visual Studio
2005\projects\CallingFortranStructures\CallingFortranStructures\recp.dll";
string entryPointName = "MDERECPRFTEST_mp_CREATETYPE1";
AssemblyBuilder dynamicAsm = null;
MethodInfo methodInfo = null;
Type[] parameterTypes = new Type[7];
parameterTypes[0] = typeof(int); //iScalar1
parameterTypes[0] = parameterTypes[0].MakeByRefType();
parameterTypes[1] = typeof(double[,]); //dArray1
parameterTypes[1] = parameterTypes[1].MakeByRefType();
parameterTypes[2] = typeof(double[,]); //dArray2
parameterTypes[2] = parameterTypes[2].MakeByRefType();
parameterTypes[3] = typeof(double); //dScalar1
parameterTypes[3] = parameterTypes[3].MakeByRefType();
parameterTypes[4] = typeof(int[]); //iArray1
parameterTypes[4] = parameterTypes[4].MakeByRefType();
parameterTypes[5] = typeof(int); //iScalar2
parameterTypes[5] = parameterTypes[5].MakeByRefType();
parameterTypes[6] = typeof(RTYPE1); //rType
parameterTypes[6] = parameterTypes[6].MakeByRefType();
// Create a dynamic assembly and a dynamic module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "CreateType1";
dynamicAsm =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
dynamicAsm.DefineDynamicModule("CreateType1");
// Dynamically construct a global PInvoke signature
// using the input information
MethodBuilder methodBuilder =
moduleBuilder.DefinePInvokeMethod(entryPointName,
fileName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
typeof(void),
parameterTypes,
CallingConvention.StdCall,
CharSet.Ansi);
methodBuilder.SetImplementationFlags(MethodImplAttributes.PreserveSig);
moduleBuilder.CreateGlobalFunctions();
// Get a MethodInfo for the PInvoke method and store it away for
later use:
methodInfo = moduleBuilder.GetMethod(entryPointName);
if (methodInfo != null)
{
//...Set up the parameters:
object[] parameterValues = new object[7];
//ParameterModifier parameterModifiers = new
ParameterModifier();
//...Set the parameter values ready for the call:
parameterValues[0] = 0;
parameterValues[1] = new double[5, 10];
parameterValues[2] = new double[5, 10];
parameterValues[3] = 0.0;
parameterValues[4] = new int[5];
parameterValues[5] = 0;
RTYPE1 rtype1 = new RTYPE1();
rtype1.iArray1 = new int[5];
rtype1.iScalar1 = 1;
rtype1.iScalar2 = 3;
rtype1.dArray1 = new double[5, 10];
rtype1.dArray2 = new double[5, 10];
rtype1.dScalar1 = 3.14;
parameterValues[6] = rtype1;
object returnValue = typeof(void);
returnValue = methodInfo.Invoke(null, parameterValues);
I appreciate that this is rather specific, but I was wondering whether
anyone could shed any light on this problem.
Thanks in advance.
Marek