Calling a FORTRAN DLL with a structure parameter

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
 
W

Walter Wang [MSFT]

Hi Marek,

Honestly, I'm not familiar with Fortran so I'm not sure if I can really
help here. Could you please tell me can you currently call the exported
Fortran function using P/Invoke declaration? If this is the case, then the
question will be how to use AssemblyBuilder and MethodInfo, right?
Otherwise, we will need to deal with Fortran specific issues first such as
the specific calling convention, etc.

I'm wondering if you could send me a binary Fortran DLL to test, that would
make this more easier to work torward a solution. Thanks for your effort.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Marek

Hi Walter
Thanks for replying - I appreciate that this is a pretty esoteric post.

I have sent you my project and binaries as requested via email.

Best regards

Marek
 
N

Nicholas Paldino [.NET/C# MVP]

Marek,

You should post to the newsgroup so that if/when a solution is
presented, others might benefit.


--
- Nicholas Paldino [.NET/C# MVP]
- (e-mail address removed)

Marek said:
Hi Walter
Thanks for replying - I appreciate that this is a pretty esoteric post.

I have sent you my project and binaries as requested via email.

Best regards

Marek

"Walter Wang [MSFT]" said:
Hi Marek,

Honestly, I'm not familiar with Fortran so I'm not sure if I can really
help here. Could you please tell me can you currently call the exported
Fortran function using P/Invoke declaration? If this is the case, then
the
question will be how to use AssemblyBuilder and MethodInfo, right?
Otherwise, we will need to deal with Fortran specific issues first such
as
the specific calling convention, etc.

I'm wondering if you could send me a binary Fortran DLL to test, that
would
make this more easier to work torward a solution. Thanks for your effort.

Regards,
Walter Wang ([email protected], remove 'online.')
Microsoft Online Community Support

==================================================
When responding to posts, please "Reply to Group" via your newsreader so
that others may learn and benefit from your issue.
==================================================

This posting is provided "AS IS" with no warranties, and confers no
rights.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top