- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have an Intel Fortran program that calls a C# function. The C# function header is a follows, it takes "stringresourcekey" and returns "stringresource" (1024 byte string) and two integers.
private void GetStringResource(
string stringresourcekey,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 1024)] byte[] stringresource,
ref int stringresourcelength_ansi,
ref int stringresourcelength_utf8)
In Fortran, I call it like this:
call GetStringResourceCallbackExternal(stringresourcekey,sStringResource,length_ansi,length_utf8)
Declarations are:
character
(len=*), intent(in) :: stringresourcekeycharacter (len=1024) :: sStringResource,out_string
integer :: &
length_ansi, & ! ANSI String length
length_utf8 ! Effective String length when displayed with UTF-8 encoding
This all works fine, the C# function is called, executes properly, and appears to return the intended values. Running in the debugger, I can see sStringResource,length_ansi,length_utf8 all returned with correct values and the intended string in sStringResource.
However when I try to use sStringResource, I have problems - if I write it to a file, the first part of it is garbage. If I try a simple assignment:
out_string = sStringResource
then the program crashes with an access violation. Any ideas what I'm doing wrong (or not doing)?
Mark Besley
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[c-sharp] public static void putusername(string value) { StringBuilder stringBuilderValue = new StringBuilder(value.Substring(0, System.Math.Min(value.Length, 4))); PUT_USERNAME(stringBuilderValue, 4); } public static string getusername() { StringBuilder stringBuilderValue = new StringBuilder(4); GET_USERNAME(stringBuilderValue, 4); return stringBuilderValue.ToString(); }[/c-sharp]
[c-sharp][/c-sharp]
[c-sharp][/c-sharp]
[c-sharp]Fortran:[/c-sharp]
[c-sharp]subroutine put_dateiname(value) use globaleVariablen implicit none character*255 dateiname dateiname = value end subroutine put_dateiname ! subroutine put_username(value) use globaleVariablen implicit none character*4 username username = value end subroutine put_username[/c-sharp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[cpp] subroutine put_dateiname(value) use globaleVariablen implicit none character*255 dateiname dateiname = value end subroutine put_dateiname ! subroutine put_username(value) use globaleVariablen implicit none character*4 username username = value end subroutine put_username[/cpp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[cpp] subroutine put_username(value) use globaleVariablen implicit none character*4 username username = value end subroutine put_username ! character*4 function get_username() use globaleVariablen implicit none getusername = username end function get_username[/cpp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have an Intel Fortran program that calls a C# function. The C# function header is a follows, it takes "stringresourcekey" and returns "stringresource" (1024 byte string) and two integers.
private void GetStringResource(
string stringresourcekey,
[In, Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 1024)] byte[] stringresource,
ref int stringresourcelength_ansi,
ref int stringresourcelength_utf8)
In Fortran, I call it like this:
call GetStringResourceCallbackExternal(stringresourcekey,sStringResource,length_ansi,length_utf8)
Declarations are:
character
(len=*), intent(in) :: stringresourcekeycharacter (len=1024) :: sStringResource,out_string
integer :: &
length_ansi, & ! ANSI String length
length_utf8 ! Effective String length when displayed with UTF-8 encoding
This all works fine, the C# function is called, executes properly, and appears to return the intended values. Running in the debugger, I can see sStringResource,length_ansi,length_utf8 all returned with correct values and the intended string in sStringResource.
However when I try to use sStringResource, I have problems - if I write it to a file, the first part of it is garbage. If I try a simple assignment:
out_string = sStringResource
then the program crashes with an access violation. Any ideas what I'm doing wrong (or not doing)?
Mark Besley
A further development - I changed nothing in the way that the calls were done and changed nothing at the C# end, but instead declared sStringResource as an array of 256 4-byte integers:
use the same call:
call GetStringResourceCallbackExternalstringresourcekey,sStringResource,length_ansi,length_utf8)
character (len=1024) :: mold,out_string1
out_string = sStringResource
I can assign this to another integer array without getting an access violation, and better still I can transfer the data into a character variable and write it out and get the intended output as follows:
Any idea why this fails if I declare the sStringResource as character but works fine if I declare it as integer? Is there some subtle difference in the way the data is handled between the two types?
out_string1 =
transfer(out_string,mold)write(unlis1,"(a)")out_string1
Mark Besley
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hallo everybody
It looks like you are familiar with calling C# from Fortran. Can you please help me with my project I attached?
Im not able link C# dll. I created interface (suppressed in code) but it doesnt work. In help is written that for .NET dll is necessary use Module Wizard for creating interface. But when I used this Wizard no interfaces crated (see. ShowNumberInterface.f90).
Can you please tell me what is necessary for making right Fortran C# mixed language solution?
I use VS2003.NET and IVF 10.1.019.
Jiri
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I do not know C#, but I do know that if you want a Fortran program to call a function in a DLL, then
a) you must make the function or symbol for the functionvisible to users of the DLL, and
b) In your Fortran code, you must use the correct symbol for the function you wish to access in the DLL, possibly using a compiler flag such as ALIAS, and
c) In your Fortran code, you must mark that symbol as to be IMPORTED from a dll using a compiler flag such as DLLIMPORT,
d) You must also, in your Fortran, ensure that the calling convention agrees with the C# one (e.g. are the arguments supplied by value or reference (i.e. address)
In your C# code,
[cpp]using System; using System.Windows.Forms; namespace prijimac { public class Class1 { public static void ShowNumber(int a, int b) { MessageBox.Show("a=" + a.ToString()+ " b=" + b.ToString()); } } } [/cpp]
There are no symbols exported, correct?. Thus, as far as I can see from your zipped archive, there is no export library (.LIB) of symbols generated and supplied along with your C# DLL, so there is no way for your Fortran program to be given the details as to what and whereare the symbols that you wish to reference in your Fortran code (normally you would include the .LIB in your Fortran project to do this). This shortcoming has to be rectified first before you stand a chance of calling functions in your DLL, IMO.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I agree with Anthony's assessment.
Exporting from a C# DLL is nonstandard and has been discussed (my me) here on this forum some time ago.
Gerry
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[cpp]// mycdll.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" // myDLL.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include "iostream.h" #include "stdlib.h" BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { return TRUE; } extern "C" __declspec(dllexport) void __stdcall MyCDllRoutine(int a, int b) ; // MAIN ENTRY FUNCTION void __stdcall MyCDllRoutine (int a, int b) { char achar[10], bchar[10], str[80]; itoa(a,achar,10); itoa(b,bchar,10); strcpy(str," a = "); strcat(str,achar); strcat(str,", b = "); strcat(str,bchar); cout <<" Entered MyCDllRoutine in the C++ DLL"< [/cpp]
[cpp]Fortran Code:[/cpp]
[cpp]!**************************************************************************** ! ! PROGRAM: testmycdll ! ! PURPOSE: Entry point for 'Hello World' sample console application to access ! a routine held in a Win32 Dynamic link library compiled from C++ code ! !**************************************************************************** program testmycdll implicit none ! INTEGER I,J INTERFACE SUBROUTINE MYCDLLROUTINE (I,J) !DEC$ ATTRIBUTES DLLIMPORT :: MYCDLLROUTINE !DEC$ ATTRIBUTES STDCALL :: MYCDLLROUTINE !DEC$ ATTRIBUTES ALIAS:'_MyCDllRoutine@8' :: MYCDLLROUTINE INTEGER I,J END SUBROUTINE MYCDLLROUTINE END INTERFACE print *, 'Hello World' I=10 J=25 CALL MYCDLLROUTINE(I,J) end program testmycdll [/cpp]
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
[cpp]cout <<" Entered MyCDllRoutine in the C++ DLL"< [/cpp]
[cpp]MessageBox(HWND_DESKTOP,str,"Two numbers sent to C++ DLL",MB_OK);
}
[/cpp]

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