Late binding to a FORTRAN DLL routine with a string paramter
am 23.10.2007 15:38:01 von dnv21Hi
I'm trying to call into a FORTRAN DLL using ModuleBuilder, MethodBuilder and
then doing an Invoke to allow users to specify the Fortran DLL Signature etc.
at runtime. All works fine with ints and doubles etc., but I just can't get
the string to work (AccessViolationException).
I am including the hidden length parameter in a fortran call so it isn't that.
The FORTRAN method is defined as follows:
! Stringtest.f90
!
! FUNCTIONS/SUBROUTINES exported from Stringtest.dll:
! Stringtest - subroutine
!
subroutine Stringtest(STRING, ITEST, LENOUT)
! Expose subroutine Stringtest to users of this DLL
!
!DEC$ ATTRIBUTES DLLEXPORT::Stringtest
! Variables
CHARACTER , INTENT(IN) :: &
STRING*(*) ! String argument
INTEGER, INTENT(OUT) :: &
ITEST, & ! Some calculation on string
LENOUT ! Length of string as check
and the code I use to try and access it (in a simple console application) is
as follows:
string fileName =
Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAsse mbly().Location),
"stringtest.dll");
string entryPointName = "STRINGTEST";
CallingConvention callingConvention = CallingConvention.Winapi;
CharSet charSet = CharSet.Ansi;
//...Set up the parameters:
Type[] parameterTypes = new Type[4];
parameterTypes[0] = typeof(string);
parameterTypes[1] = typeof(int);
parameterTypes[2] = typeof(int).MakeByRefType();
parameterTypes[3] = typeof(int).MakeByRefType();
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "Assembly Name";
AssemblyBuilder dynamicAsm =
AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName,
AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
dynamicAsm.DefineDynamicModule("StringTest");
MethodBuilder methodBuilder =
moduleBuilder.DefinePInvokeMethod(entryPointName,
fileName,
MethodAttributes.Static | MethodAttributes.Public |
MethodAttributes.PinvokeImpl,
CallingConventions.Standard,
typeof(void),
parameterTypes,
callingConvention,
charSet);
methodBuilder.SetImplementationFlags(MethodImplAttributes.Pr eserveSig);
moduleBuilder.CreateGlobalFunctions();
// Get a MethodInfo for the PInvoke method and store it away for
later use:
MethodInfo methodInfo = moduleBuilder.GetMethod(entryPointName);
//...Set up the parameters:
object[] parameterValues = new object[parameterTypes.Length];
parameterValues[0] = "Hello";
parameterValues[1] = 5;
parameterValues[2] = 0;
parameterValues[3] = 0;
ParameterModifier parameterModifiers = new ParameterModifier();
//object returnValue = typeof(void);
try
{
/*returnValue = */methodInfo.Invoke(null, parameterValues);
int loop = 0;
foreach (object parameterValue in parameterValues)
{
Console.WriteLine(String.Format("{0}. {1}", loop,
parameterValue.ToString()));
loop++;
}
}
catch (Exception exception)
{
Console.WriteLine(exception.ToString());
}
Console.ReadKey();
}
If anyone can shed any light on this that would be great.
Best regards
Marek