- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I posted an early thread this morning, using the C#&Fortran.
But no one give me even a single answer, so I switch to VC++&Fortran(DLL).
But I encounter the same problem:Unhandled exception at 0x10001082 in MFCMainTest.exe: 0xC0000005: Access violation reading location 0x00000007.
Then I switch to so I switch to VC++&Fortran(Static library),then I got another problem:Error1error LNK2019: unresolved external symbol _TEST@12 referenced in function _dynamicLIBSTRING_Cbridge.obj
I put the whole code in the attachment, I hope some guys can get me out of here.
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I's like to try and help, but I do not have the application needed to read your archived file.
Why noy post it as simple text - It cannot be that large a file surely?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I would point out that the short sample first posted seems to indicate that the different string termination requirements of the languages are being ignored, unless the DEC$ directives somehow cover this. If you feel that it is necessary to depend on those specific features, rather than standard Fortran, when using C#, my interest declines sharply.
Among the advertised features of C# are relatively easy debugging, so you should be able to step the C# code after returning from Fortran to see if you have in fact programmed a buffer over-run.
As pointed out in recent examples, you can handle null character string termination explicitly in Fortran. The case may also make the point of defensive C programmers about using the strn functions to guard against over-runs.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I thought that theremay besome problems with the project settings, so I put all the solution in one single winrar file.
Thanks for your reply.
________________________________________________
1.Dynamic library
________________________________________________
Fortran:
! dynamiclib.f90
!
! FUNCTIONS/SUBROUTINES exported from dynamiclib.dll:
! dynamiclib - subroutine
!
SUBROUTINE dynamicLIBSTRING(DATA_FILE,Error,Message)
!DEC$ ATTRIBUTES DLLEXPORT::DYNAMICLIBSTRING
!DEC$ ATTRIBUTES ALIAS:"dynamicLIBSTRING"::DYNAMICLIBSTRING
CHARACTER*(*) DATA_FILE
CHARACTER*(*) Message
integer:: Error
OPEN(12,FILE=DATA_FILE,FORM='FORMATTED',MODE='WRITE')
WRITE(12,*) Error
WRITE(12,*) DATA_FILE
WRITE(12,*) Message
CLOSE(12)
END SUBROUTINE
__________________________
bridge.h
#include "stdafx.h"
#include
typedef void (__stdcall *dynamicLIBSTRING)(char * name,int len,int* errnum,char * msg,int len1);
#ifdef __cplusplus
extern "C" {
#endif
_declspec(dllexport) void dynamicLIBSTRING_C(char * name,int len,int errnum,char * msg,int len1);
#ifdef __cplusplus
}
#endif
__________________________
bridge.cpp
#include "stdafx.h"
#include "bridge.h"extern "C" _declspec(dllexport) void dynamicLIBSTRING_C(char * name,int len,int errnum,char * msg,int len1)
{
HINSTANCE hDLL;
dynamicLIBSTRING dynamicLIBSTRING1;
hDLL=LoadLibrary(TEXT("dynamiclib.dll"));
dynamicLIBSTRING1=(dynamicLIBSTRING)GetProcAddress(hDLL,("dynamicLIBSTRING"));
dynamicLIBSTRING1(name,len,&errnum,msg,len1);
FreeLibrary(hDLL);
}
__________________________
MFCMainTestDlg.cpp
void CMFCMainTestDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
char* name;
name = "123.bdg";
int len = strlen(name);
int errnum = 0;
char* msg;
msg = "";
int len1 = strlen(msg);
dynamicLIBSTRING_C(name,len,errnum,msg,len1);
OnOK();
}
________________________________________________
2.static library
________________________________________________
Fortran:
subroutine TEST(x,y,z)
real*8:: z
open(10,file='alpha.out',form='formatted',status='UNKNOWN')
write(10,'("staticlib:")')
write(10,'(2F10.2)') x,y
z = 10
write(10,'("staticlib1:")')
write(10,'(F10.2)') z
z = x+y
write(10,'("staticlib2:")')
write(10,'(F10.2)') z
end subroutine TEST__________________________
bridge.h
#include "stdafx.h"
#include#ifdef __cplusplus
extern "C" {
#endif
void __stdcall TE ST(float *x,float*y,float*z);
#ifdef __cplusplus
}
#endif__________________________
bridge.cpp
#include "stdafx.h"
#include "bridge.h"extern "C" _declspec(dllexport) void dynamicLIBSTRING_C(char * name,int len,int errnum,char * msg,int len1)
{
float x = 10;
float y = 10;
float z = 10;
TEST(&x,&y,&z);
}__________________________
MFCMainTestDlg.cpp
void CMFCMainTestDlg::OnBnClickedOk()
{
// TODO: Add your control notification handler code here
char* name;
name = "123.bdg";
int len = strlen(name);
int errnum = 0;
char* msg;
msg = "";
int len1 = strlen(msg);
dynamicLIBSTRING_C(name,len,errnum,msg,len1);
OnOK();
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks tim.
My computer justbreakdown today, so I have to rebind the system rightnow. It may take a little time to have VS 2005 & Fortran to be ready. So I can't try your advice rightnow.
You mentioned that "As pointed out in recent examples, you can handle null character string termination explicitly in Fortran", please let me know how to treat character *(*) type with null character string termination.
I think "null character string termination " is the problem, do you think 'decorate directive' make any sense? And the problem I encounter is related to "ANSI&unicode"?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The static library is quite simple, why the C++ compiler give me the error "unresolved external symbol _TEST@12 referenced in function ", God, please save me.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In the C code, take out
_stdcall
That is causing the link error.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve.
Didyou mean I have to use the reference directive? I have no idea of the Index function, would you please give some tips.
BTW, I have found this site:http://www.nag.co.uk/numeric/FL/flassocinfo/csharp/g02eafe.cs
in which he can use the arguments in this way: "string mean, int length_mean,string weight, int length_weight,ref int n, ref int m". So I think there may be some kind of setting can automatically look for the NULL. I want to hear your point.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I meant to use:
!DEC$ ATTRIBUTES REFERENCE :: varname
in the Fortran code. This tells the compiler to not look for the passed lengths.
To use INDEX, do something like this:
integer strinng_len
...
string_len = index (string_var, CHAR(0))
Now you can reference string_var(1:string_len)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve.
I use the same way as the reference, but didn't work, why? what's your "That works too if you make sure to put them at the end of the argument list." exactly mean?
- 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 suggest that you study the C_calls_Fortran sample provided with the product. It demonstrates passing strings.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve.
Where can I find the C_calls_Fortran sample, I have been looking around for a lot of times, but can't find.
Myfortran is the evaluation version 9.1 downloaded from this site.
- 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
Thanks,Steve.
I've already fixed my problem with the help of the sample code, the main factor is that the string length argument have to put after all the argument.
And I've also figure out how to connect between C# and Fortran. But I found a newly problem, I can't step into the Fortran code from the C# graphic interface, I have searched around this forum, andcheck "Enable unmanaged code debugging" box ,but still not work, I attach the simple code in the attachment, will youplease figure out the problem?
- 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
Set the FORTRAN project as Startup instead of C# project and set break point anywhere in the FORTRAN soubroutine. This should work.
If you put a breakpoint in the FORTRAN routine, even if the startup project is C# one, it should stop at there. But Stepping in to the function from C# code doesnt work.
- 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
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I have similar problem and that is why I got interested to look at your project. But mine is slightly different, as I am trying to pass a string from C++ code and then change it inside FORTRAN routine and carry back the changed string out of FORTRAN routine.
I have to use CVF (/iface:cvf) calling convention and set "String Length Argument Passing" as "After Individual String Argument". FORTRAN code is as follows
IGET_NS_X.for
SUBROUTINE GetFortranMsg(iMsgID,iChar,szMsg)
!MS$ATTRIBUTES c,alias: '_GetFortranMsg'::GetFortranMsg
INCLUDE 'bbb_X.fi' CHARACTER,POINTER:: szMsg INTEGER,POINTER:: iMsgID INTEGER,POINTER:: iChar CHARACTER szCopyMsg*260 szCopyMsg = "It is the string inside FORTRAN code."//char(0) szMsg = szCopyMsg RETURN END
C++code is as follows:
Engine.cpp
extern
"C" void GetFortranMsg(int* iMsgID,int*ichar,char* szMsg, size_t length_arg);...
void
CEngine::PrintMessage(){
int
iMsgID = 1; char *szMsg = new char[256]; int ichar=10;lstrcpy(szMsg,
"This string has been assigned in C++ code."); int l = strlen(szMsg);GetFortranMsg(&iMsgID,&ichar,szMsg,l);
AfxMessageBox(szMsg);
if(szMsg) delete [] szMsg;}
With above code, I always get the first character of szMsg in FORTRAN code and hence any change made in there would only modify the first character. I have checked the samples provided in IVF 10 and that also behaves in the same way if CVF calling convention is set. Is there any way out other than looping over all along the string length and fetch one character at a time from FORTRAN code.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
SUBROUTINE GetFortranMsg(iMsgID,iChar,szMsg)
!MS$ATTRIBUTES c,reference,decorate,alias: 'GetFortranMsg'::GetFortranMsg
INCLUDE 'bbb_X.fi'
CHARACTER(*):: szMsg
INTEGER :: iMsgID
INTEGER :: iChar
CHARACTER szCopyMsg*260
szCopyMsg = "It is the string inside FORTRAN code."//char(0)
szMsg = szCopyMsg
RETURN
END

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