- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I'm having a bit of trouble using a Fortran dll in my C# code. I've stripped down my Fortran code to the bare minimum:
subroutine
Dll1 !Expose subroutine Dll1 to users of this DLL !DEC$ ATTRIBUTES DLLEXPORT::Dll1 !DEC$ ATTRIBUTES ALIAS:'_Dll1'::Dll1 !DEC$ ATTRIBUTES STDCALL, REFERENCE :: Dll1 ! Variables ! Body of Dll1end subroutine
Dll1i.e. an empty subroutine (although I have tried the same for more complicated functions). The second two !DEC lines I added after looking around the forum for a bit. They may be extraneous, but it doesn't work if I remove them anyhow. My C# code is:
using
System;using
System.Collections.Generic;using
System.Text;// Need InteropServices for DLL integration
using
System.Runtime.InteropServices;namespace
ConsoleApplication1{
class Program{
[
DllImport("Dll1.dll")] public static extern void dll1(); static void Main(string[] args){
dll1();
}
}
}
So, again pretty simple. The problem I get is that when I get to the call of dll1() I find the error:
"An unhandled exception of type 'System.EntryPointNotFoundException' occurred in ConsoleApplication1.exe
Additional information: Unable to find an entry point named 'dll1' in DLL 'Dll1.dll'."
The program is picking up the dll correctly because if I remove it then I get a different error. My thoughts are that it might be something to do with registry, because if I check the automatic registration project option then it spits out a PRJ0019error (but only in debug mode). Also, neither the debug or release versions register successfully with regsvr32.
Using the dependency walker and "DUMPBIN /exports dll1.dll" both bring up "dll1()" in the list of functions. So now I'm out of ideas... any help or advicewould be extremely appreciated. T hanks.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I cant reproduce your problem because I dont have C# any more on my business machine. But once I wrote a C# using Fortran DLL project, maybe this may help you. Its very simple:a function that returns a^b and a subroutine that returns a + b within the parameter list.
Fortran code:
subroutine FORTRANSUBROUTINE (summandA, summandB, summeC)
implicit none
integer*4 summandA, summandB, summeC
summeC = summandA + summandB
return
end subroutine
real*8 function FORTRANFUNCTION (basisA, exponentB)
implicit none
real*8 basisA, exponentB
FORTRANFUNCTION = basisA**exponentB
return
end function
C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace Fortran_mit_Csharp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("fortrandll.dll")]
unsafe private extern static void FORTRANSUM(int summandA, int summandB, int *summeC); [DllImport("fortrandll.dll")]
private extern static double EXPFUNCTION(double basisA, double exponentB);private void buttonFunction_Click(object sender, EventArgs e)
{
double ergebnis,basis,exponent;
basis = 2.4d;
exponent = 3.7d;
labelText.Text = "2,4 hoch 3,7 ergibt";
ergebnis = EXPFUNCTION(basis, exponent);
textBoxErgebnis.Text = ergebnis.ToString();
}
unsafe private void buttonSubroutine_Click(object sender, EventArgs e)
{
int a=5, b=9, ergebnis=0;
FORTRANSUM(a,b,&ergebnis);
labelText.Text = "5 + 9 ergibt";
textBoxErgebnis.Text = ergebnis.ToString();
}
}
}
Markus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- You have "Dll1" in the Fortran code, but "dll1" in C# code (note the capitalization difference). See the capitalization in OnkelHotte's working code. I doubt that Dependency walker really gives the uppercased name.
- You have a recipe for disaster by specifying explicit ALIAS. In effect, you made a STDCALL routine, but didn't specify __stdcall on C#side, and in addition you hide it by providing C-style name mangling in the ALIAS. Even if you manage to call the routine, it will blow the stack. [It's as if you fit a .30" bullet into a 7.65mm rifle with a help of a hand-file -- it will ultimately get in, but when you try to fire from it...]. The bottom line: if you must use ALIAS, always combine it with DECORATE.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for the help everybody. It was just a capitalisation error. I changed to Dll1 to dll1 and it worked. Jugoslav's point 2 is a little over my head at the moment, so I'll go and do a bit more research...
P.S. I'm using Intel Fortran.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
1) You said "Stdcall" on Fortran side, but not on C# side (see counterxample code).
2) As result, C# will use some default (unknown to me, most likely __cdecl/C)
3) When C# calls Fortran, the stack will be corrupted due to different calling conventions. Something ugly happens. For routines without arguments, such as Dll1, no harm will be done, but it's quite likely for more complicated ones (making it even more hard to find the problem).
When you specified !DEC$ATTRIBUTES ALIAS: "_dll1", you were actually hiding the crime. If you hadn't done that, you would have got a warning about missing import (C# expects cdecl "_dll1" but Fortran provides stdcall "_dll1@0"), because you mismatched the calling conventions. Rather than fixing the problem (calling convention mismatch), you fixed the symptom (different name decoration).
ALIAS is sometimes necessary to specify CamelCase symbol names, but it should generally be accompanied with DECORATE, to prevent the said "hiding the crime".
Solution: check C# documentation on default calling convention. Most probably, replace STDCALL with C on Fortran side; alternatively, use
CallingConvention=CallingConvention.StdCall on C# sideUse just !DEC$ATTRIBUTES DECORATE, ALIAS: "dll1" whichever approach you take.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page