- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I havea Fortran dll that is called from C#. Essentially, the Fortran dll creates some binary files that the C# app then reads. Now, instead of creating the binary files, it is desired to have the data passed directly to the C# app as some sort of object.Is this possible? Maybe if I modified the existing fortran code to be Fortran 2003 compliant? If it is possbile either with Fortran 90/95/2003 is there some documentation on how to do that?
1 Solution
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok. A TYPE is like a C struct.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
[plain]module employee
use iso_c_binding
type, bind(C) :: employee_type
character(12) :: emplid
character(8) :: emplpermnum
character(50) :: empladdr
character(50) :: emplcity
character(50) :: emplstate
character(10) :: emplzip
end type employee_type
contains
function new_employee () bind(C)
type(C_PTR) :: new_employee
type(employee_type), pointer :: new_emp
allocate(new_emp)
! Fill in fields...
new_emp%emplid = ... something ...
...
! Convert Fortran pointer to C pointer
new_employee = c_loc(new_emp)
! Return pointer to new employee
return
end function new_employee
! Add get and put functions if needed
! Also add a "deallocate" routine if required
end module employee[/plain]
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
Link Copied
15 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - daninraleigh
I havea Fortran dll that is called from C#. Essentially, the Fortran dll creates some binary files that the C# app then reads. Now, instead of creating the binary files, it is desired to have the data passed directly to the C# app as some sort of object.Is this possible? Maybe if I modified the existing fortran code to be Fortran 2003 compliant? If it is possbile either with Fortran 90/95/2003 is there some documentation on how to do that?
Search the forum, there are a few threads with discussion about passing data from a Fortran DLL to a C# project.
The only "difficulty" are character and array passing. In C# you need an object of stringbuilder class to receive a character value and arrays are stored the other way round (fortran[x,y] -> c#[y,x]).
Markus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - onkelhotte
Search the forum, there are a few threads with discussion about passing data from a Fortran DLL to a C# project.
The only "difficulty" are character and array passing. In C# you need an object of stringbuilder class to receive a character value and arrays are stored the other way round (fortran[x,y] -> c#[y,x]).
Markus
Thanks Markus, but I must not have been clear in my post. I am already passing data between Fortran and C#. However, rather than currently passing individual strings/characters/integers back and forth between C# and Fortran, I also want to now pass an entire object(what the contents of a binary file currently is from Fortran to C#). Has anyone done this? Is it possible? Can I do this in Fortran 2003 with OOP?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The C interoperability features in Fortran 2003 are not "C++ interoperability". There is no notion of Fortran and C++ sharing a representation for "objects". So, you will have to pass data in a form that would be acceptable to C in order to do so in any kind of portable manner.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
The C interoperability features in Fortran 2003 are not "C++ interoperability". There is no notion of Fortran and C++ sharing a representation for "objects". So, you will have to pass data in a form that would be acceptable to C in order to do so in any kind of portable manner.
Hello Lionel,
I was not asking about C interoperability. I figure since I can already pass Characters and Integers in the non-OOP Fortran, that hopefully with the somewhat OOP-Fortran2003 I could pass a data object. Are you saying this is not possible?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Please clarify what you mean by "a data object". Can you show in "pseudo-code" what you'd like to do?
Fortran 2003's OOP features include the ability to have a variable of dynamic type. The dynamic type information is Fortran-specific and would not be understood by C#. Conversely, passing a dynamic type object from C# to Fortran would not be understood. It is possible to pass the actual data, but you must do so in a context where the type is fixed (this could be within a SELECT TYPE construct in Fortran, for example.)
I should note that Intel Fortran 11.0 does not support dynamic types. Version 11.1 will.
Fortran 2003's OOP features include the ability to have a variable of dynamic type. The dynamic type information is Fortran-specific and would not be understood by C#. Conversely, passing a dynamic type object from C# to Fortran would not be understood. It is possible to pass the actual data, but you must do so in a context where the type is fixed (this could be within a SELECT TYPE construct in Fortran, for example.)
I should note that Intel Fortran 11.0 does not support dynamic types. Version 11.1 will.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
Please clarify what you mean by "a data object". Can you show in "pseudo-code" what you'd like to do?
Fortran 2003's OOP features include the ability to have a variable of dynamic type. The dynamic type information is Fortran-specific and would not be understood by C#. Conversely, passing a dynamic type object from C# to Fortran would not be understood. It is possible to pass the actual data, but you must do so in a context where the type is fixed (this could be within a SELECT TYPE construct in Fortran, for example.)
I should note that Intel Fortran 11.0 does not support dynamic types. Version 11.1 will.
Fortran 2003's OOP features include the ability to have a variable of dynamic type. The dynamic type information is Fortran-specific and would not be understood by C#. Conversely, passing a dynamic type object from C# to Fortran would not be understood. It is possible to pass the actual data, but you must do so in a context where the type is fixed (this could be within a SELECT TYPE construct in Fortran, for example.)
I should note that Intel Fortran 11.0 does not support dynamic types. Version 11.1 will.
Hi Lionel,
Thanks for continuing to help me on this. I think I can see now how my initial question is confusing.
What I would like to do is create a Fortran 2003 MODULE or maybe a TYPE???(not sure what these are yet)? Such as this that has all the values from a file:
MODULE EMPLOYEE
CHARACTER(LEN=12) :: EMPLID = IDFROMFILE
CHARACTER(LEN=8) :: EMPLPERMNUM = NUMBERFROMFILE
CHARACTER(LEN=50) :: EMPLADDR = ADDRFROMFILE
CHARACTER(LEN=50) :: EMPLCITY = CITYFROMFILE
CHARACTER(LEN=50) :: EMPLSTATE = STATEFROMFILE
CHARACTER(LEN=10) :: EMPLZIP = ZIPFROMFILE
END MODULE EMPLOYEE
In C# or Java I might do something like this:
public class Employee {
// data member variables
private string emplId;
private string emplPermNum;
private string emplAddr;
private string emplCity;
private string emplState;
private string emplZip;
//getters
public String getEmplId() {
return this.emplId;
}
...more getters/setters...
//Class constructor
public Employee(string emplId) {
this.emplId = emplId;
}
//methods that populate the data member variables
....
}
THEN in another C# Class, call the Fortran 2003 DLL's object/module/type and it's indiviual variable values
// this is how C# would instantiate the c# class object. Maybe C# calling the Fortran 2003 object/module/type would // be different
Employee emp = new Employee(3546289);
// then use the variables from the Employee class object/module/type
something = emp.EmplPermNum;
somethingElse = emp.EmplAddrr;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Ok. A TYPE is like a C struct.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
[plain]module employee
use iso_c_binding
type, bind(C) :: employee_type
character(12) :: emplid
character(8) :: emplpermnum
character(50) :: empladdr
character(50) :: emplcity
character(50) :: emplstate
character(10) :: emplzip
end type employee_type
contains
function new_employee () bind(C)
type(C_PTR) :: new_employee
type(employee_type), pointer :: new_emp
allocate(new_emp)
! Fill in fields...
new_emp%emplid = ... something ...
...
! Convert Fortran pointer to C pointer
new_employee = c_loc(new_emp)
! Return pointer to new employee
return
end function new_employee
! Add get and put functions if needed
! Also add a "deallocate" routine if required
end module employee[/plain]
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
Ok. A TYPE is like a C struct.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
You cannot use C# "new" to create an object of a Fortran type. What you could do is something like this:
[plain]module employee
use iso_c_binding
type, bind(C) :: employee_type
character(12) :: emplid
character(8) :: emplpermnum
character(50) :: empladdr
character(50) :: emplcity
character(50) :: emplstate
character(10) :: emplzip
end type employee_type
contains
function new_employee () bind(C)
type(C_PTR) :: new_employee
type(employee_type), pointer :: new_emp
allocate(new_emp)
! Fill in fields...
new_emp%emplid = ... something ...
...
! Convert Fortran pointer to C pointer
new_employee = c_loc(new_emp)
! Return pointer to new employee
return
end function new_employee
! Add get and put functions if needed
! Also add a "deallocate" routine if required
end module employee[/plain]
Since you're calling from C# and maybe Java, you'll need to put this into a DLL which will then require ATTRIBUTES DLLEXPORT directives for the routines, such as new_employee. The Fortran code may need to append C_NULL_CHAR to the trimmed value if the C# code wants NUL termination.
On the C# side, you'd have to declare what is essentially a C struct that has the same layout and declare new_employee as returning a pointer to that struct type.
I don't know if this meets your needs. I can tell you that a C# class is not something that Fortran can do anything with, and vice-versa.
Thanks Lionel,
I am completely new to pointers :-)
As a test I have put together a simple exe and dll based on the code below. I have tried the following in C# to create the pointer you spoke of. While trying to run I get an error message stating it cannot find the employee.dll. Which is odd as I have the dll employee.dll in the same direcotry as the test c# application. Am I creating and calling the pointer correctly to begin with?
[c-sharp]using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApp { class Program { [DllImport("employee.dll", EntryPoint = "new_employee", CallingConvention = CallingConvention.StdCall)] private static extern void new_employee(); [StructLayout(LayoutKind.Sequential)] public class EMPLOYEE_TYPE { public string strEmplid; public string strEmplpermnum; public string strEmpladdr; public string strEmplcity; public string strEmplstate; public string strEmplzip; } static void Main(string[] args) { EMPLOYEE_TYPE et = new EMPLOYEE_TYPE(); et.strEmpladdr = new string('*', 50); new_employee(); Console.WriteLine(et.strEmpladdr); } } }[/c-sharp]
along with the following Fortran code
[cpp]! employee.f90 ! ! FUNCTIONS/SUBROUTINES exported from employee.dll: ! employee - subroutine ! module employee use iso_c_binding ! Variables ! Body of employee type, bind(C) :: employee_type character(12) :: emplid character(8) :: emplpermnum character(50) :: empladdr character(50) :: emplcity character(2) :: emplstate character(10) :: emplzip end type employee_type contains function new_employee() bind(C) ! Expose function new_employee to users of this DLL !DEC$ ATTRIBUTES DLLEXPORT::new_employee type(C_PTR) :: new_employee type(employee_type), pointer :: new_emp allocate(new_emp) ! Fill in fields... new_emp%emplid = 'ABCDEFG' new_emp%emplpermnum = '123456' new_emp%empladdr = '789 main street' new_emp%emplcity = 'San Diego' new_emp%emplstate = 'CA' new_emp%emplzip = '92124' ! Convert Fortran pointer to C pointer new_employee = c_loc(new_emp) ! Return pointer to new_employee return end function new_employee end module employee[/cpp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
FYI - my first name is Steve.
I see a couple of problems off the bat. You have specified STDCALL in the C# - does it allow "C" or some variant as the calling convention? If you must use STDCALL, then remove the BIND(C) from the "function new_employee" line and add !DEC$ ATTRIBUTES STDCALL :: new_employee.
Second is that the exported name may not match what you have in the C#, though if you drop the stdcall from the C# it should match up. That would be the preferable solution.
The C# application is going to look for the DLL in the current directory, whatever that is. Try putting in an explicit path for now and see if that works.
I see a couple of problems off the bat. You have specified STDCALL in the C# - does it allow "C" or some variant as the calling convention? If you must use STDCALL, then remove the BIND(C) from the "function new_employee" line and add !DEC$ ATTRIBUTES STDCALL :: new_employee.
Second is that the exported name may not match what you have in the C#, though if you drop the stdcall from the C# it should match up. That would be the preferable solution.
The C# application is going to look for the DLL in the current directory, whatever that is. Try putting in an explicit path for now and see if that works.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
FYI - my first name is Steve.
I see a couple of problems off the bat. You have specified STDCALL in the C# - does it allow "C" or some variant as the calling convention? If you must use STDCALL, then remove the BIND(C) from the "function new_employee" line and add !DEC$ ATTRIBUTES STDCALL :: new_employee.
Second is that the exported name may not match what you have in the C#, though if you drop the stdcall from the C# it should match up. That would be the preferable solution.
The C# application is going to look for the DLL in the current directory, whatever that is. Try putting in an explicit path for now and see if that works.
I see a couple of problems off the bat. You have specified STDCALL in the C# - does it allow "C" or some variant as the calling convention? If you must use STDCALL, then remove the BIND(C) from the "function new_employee" line and add !DEC$ ATTRIBUTES STDCALL :: new_employee.
Second is that the exported name may not match what you have in the C#, though if you drop the stdcall from the C# it should match up. That would be the preferable solution.
The C# application is going to look for the DLL in the current directory, whatever that is. Try putting in an explicit path for now and see if that works.
Thanks Steve,
Honestly, my error message was: Unhandled Exception: System.DllNotFoundException: Unable to load DLL 'employee.dll': The specified module could not be found.
So, after adding libifcoremdd.dll and libmmd.dll I do not get the error anymore. However, I do not get any output :-(
Any ideas on how this could be changed?
I also changed the DllImport statement to this:
[c-sharp][DllImport("employee.dll", EntryPoint = "new_employee", CallingConvention = CallingConvention.Cdecl)]
so the class looks like this now:using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApp { class Program { [DllImport("employee.dll", EntryPoint = "new_employee", CallingConvention = CallingConvention.Cdecl)] private static extern void new_employee(); [StructLayout(LayoutKind.Sequential)] public struct employee_type { public string strEmplid; public string strEmplpermnum; public string strEmpladdr; public string strEmplcity; public string strEmplstate; public string strEmplzip; } static void Main(string[] args) { employee_type et = new employee_type(); new_employee(); Console.WriteLine(et.strEmplid); Console.WriteLine(et.strEmpladdr); } } } [/c-sharp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I think you missed the part where I said that the Fortran function returns a pointer to a "struct" with the new data. You just called the routine and discarded its return value. I did note that there is no interaction with the C# class object.
Perhaps I misunderstood what you wanted the Fortran code to do?
Perhaps I misunderstood what you wanted the Fortran code to do?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Quoting - Steve Lionel (Intel)
I think you missed the part where I said that the Fortran function returns a pointer to a "struct" with the new data. You just called the routine and discarded its return value. I did note that there is no interaction with the C# class object.
Perhaps I misunderstood what you wanted the Fortran code to do?
Perhaps I misunderstood what you wanted the Fortran code to do?
In the C# code I am trying to print out the inidivual values from the Fortran function new_employee. I have searched everywhere on how to get the pointer that is pointing to the struct/type in Fortran. Have also tried for C, and am running a little short apparently. I thought I was close :-(
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
To those that are interested, solution found with the following C# code:
[c-sharp]using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.InteropServices; namespace ConsoleApp { class Program { [DllImport("employee.dll", EntryPoint = "new_employee", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr new_employee(); [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct employee_type { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 12)] public string strEmplid; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] public string strEmplpermnum; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] public string strEmpladdr; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] public string strEmplcity; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 2)] public string strEmplstate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string strEmplzip; } static void Main(string[] args) { employee_type et = (employee_type)Marshal.PtrToStructure(new_employee(), typeof(employee_type)); Console.WriteLine("Employee ID: "" + et.strEmplid + """); Console.WriteLine("Employee Permit Number: "" + et.strEmplpermnum + """); Console.WriteLine("Employee Address: "" + et.strEmpladdr + """); Console.WriteLine("Employee City: "" + et.strEmplcity + """); Console.WriteLine("Employee State: "" + et.strEmplstate + """); Console.WriteLine("Employee Zip: "" + et.strEmplzip + """); } } }[/c-sharp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Yep - that's the ticket.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
daninraleigh or Steve
I realize this is an old post but hopefully you'll see this and reply.
I've been trying to figure out how to pass strings inside a structure from C# to Fortran. I'm trying to pass them in a subroutine rather than the result of a function. Is this possible? Could your methodology be applied to that case?
I can get a stringbuilder class to pass outside of a structure and return values back but stringbuilders aren't allowed in a structures for some reason. Even if I could pass a structure with strings by value and not change them in Fortran that would probably be helpful although being able to change them would be ideal.
Also I would like to pass arrays in a structure and am still struggling with that as well. Any thoughts on how to do this or if it's possible?
Thanks a lot
I realize this is an old post but hopefully you'll see this and reply.
I've been trying to figure out how to pass strings inside a structure from C# to Fortran. I'm trying to pass them in a subroutine rather than the result of a function. Is this possible? Could your methodology be applied to that case?
I can get a stringbuilder class to pass outside of a structure and return values back but stringbuilders aren't allowed in a structures for some reason. Even if I could pass a structure with strings by value and not change them in Fortran that would probably be helpful although being able to change them would be ideal.
Also I would like to pass arrays in a structure and am still struggling with that as well. Any thoughts on how to do this or if it's possible?
Thanks a lot

Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page