I'm having a problem getting some unmanaged code to link into a program I'm writing. I have some FORTRAN legacy code that I don't have the option of rewriting, and I need to link several pieces of it together, as well as create a GUI for it. I've created a wrapper class for it using a DLLimport statement and I keep running into the following error:
System.BadImageFormatException was unhandled
Message="An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)"
Source="FORTlib"
where FORTlib is my wrapper class. The code is attached, the mentioned dll is the dll named in the code, called "readFile.dll". Surprising I know. This is a very simple piece of code, I'm just simply trying to link the two right now before I go much further and deeper into what I'm trying to do with it.
Imports System
Imports
System.IOImports
System.Runtime.InteropServicesFriend
Class fortranNativeMethods 'import fortran file reader dll<DllImport(
"readFile.Dll")> Public Shared Function READFILE(ByVal fileName As String) As String End FunctionEnd
ClassPublic
Class readWrapper 'wrapper method Public Function readFile(ByVal fileName) As String Return fortranNativeMethods.READFILE(fileName) End FunctionEnd
Class
Bringing in FORTRAN dlls using DLLimport
RPagels
There are basically two way to make your external dll reference in VB:
http://msdn.microsoft.com/library/default.asp url=/library/en-us/vblr7/html/vastmDeclare.asp
Declare Statement
Used at module level to declare references to external procedures in a dynamic-link library (DLL).
Remarks
For Function procedures, the data type of the procedure determines the data type it returns. You can use an As clause following arglist to specify the return type of the function. Within arglist, you can use an As clause to specify the data type of any of the arguments passed to the procedure.
Example
The following example declares a function that returns the current user name.
The DllImport attribute provides an alternative way of using functions in unmanaged code. The following example declares an imported function without using a Declare statement.
' Add an Imports statement at the top of the class or module ' where the DllImport attribute will be used. Imports System.Runtime.InteropServices '... <DllImport("KERNEL32.DLL", EntryPoint:="MoveFileW", SetLastError:=True, _ CharSet:=CharSet.Unicode, ExactSpelling:=True, _ CallingConvention:=CallingConvention.StdCall)> _ Public Shared Function _ MoveFile(ByVal src As String, ByVal dst As String) As Boolean ' This function copies a file from the path src to the path dst. ' Leave function empty - DLLImport attribute forces calls ' to MoveFile to be forwarded to MoveFileW in KERNEL32.DLL. End Functionozakiweb
This is just a WAG because I'm unfamiliar with Fortran data types, but...i'm betting it is an issue of how the string is being passed nad what fortran expects as a string...ie a null terminated string or a pointer to a string etc....in either case take a look at the marshal class which enables data type transformations for unmannaged code:
Marshal Class:
http://msdn.microsoft.com/library/default.asp url=/library/en-us/cpref/html/frlrfSystemRuntimeInteropServicesMarshalClassTopic.asp
Marshal.StringToBSTR Method
Marshal.StringToCoTaskMemAnsi Method
Marshal.StringToHGlobalAuto Method
Marshal.StringToHGlobalUni Method
are just a few of the string conversion methods that may be of interest
Mike3983
Anarchy
I think you can change the calling convention by adding the following to your fortran subroutine:
!DEC$ ATTRIBUTES C, ALIAS:'FooFunc_' :: FooFunc
It depends on your particular compiler, but doing a quick search on the internet I've seen several examples from several vendors that use this syntax, so I think it will probably work for you.
-Scott Wisniewski
Tyrael Tong
Unless your FORTRAN compiler has specific support for COM, you can't reference the fortran library via com. You would have to writer a wrapper dll in another language that supports the pascal calling convention, such as C++.
Did you check to see if your FORTRAN compiler supports changing the calling convention
That would probably be the easiest way to get things to work.
-Scott
Koray Samsun
PhilipDaniels
If so, try either a) removing it, or b) using the aliased name (i.e. readfile_) in the VB file.
-Scott
Zapp
Also, you may want to add this:
!dec$ attributes dllexport :: FooFunc
Kumar Venkat
This may be caused because FORTRAN uses a differnt calling covention (a protocol for manipulating the stack and registers) than C does, and the VB declare statement is desgined to allow you to call into functions that conform to the C calling convention (like the WIN32 api).
Does your fortran compiler have any syntax that enables you to specify calling conventions If so, I would try recompiling the function specifying the C calling convention.
If that doesn't work or is not an option, you could write a wrapper dll in C++ that access the fortran dll using the __pascall calling convention(something like extern void __pascall MyCoolFunction() ) and then expose the methods in one of three ways:
1) Via a c wrapper function
2) Via managed C++
3) Via COM
If this option is not attractive, I beleive this company: http://www.lahey.com/lf71/lfnet.htm#compiler
as a fortran compiler that targets the CLR. You may be able to use their tool to recompile the app as a managed dll which you could then add directly as a reference to your VB project.
Hope this helps!
-Scott Wisniewski
MS VB Compiler Dev
EmekaAwagu
What was the fix for the previous issue
Also, did you add the dll export declaration to the fortran function
If not, try adding it.
Eric van Feggelen