Home > Archive > Fortran > February 2007 > How calling a cpp-dll?
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
How calling a cpp-dll?
|
|
| Astrid Kuhr 2007-02-12, 7:09 pm |
|
Hello!
With my Windowsfortran I want to call a dll/lib,
which is based on cpp.
program test
implicit none
interface
subroutine stdvar_string(StdVar_ByValString)
!DEC$ ATTRIBUTES DLLIMPORT,STDCALL :: stdvar_string
character(*) :: StdVar_ByValString
end subroutine
end interface
character(15) :: StdVar_ByValString
StdVar_ByValString=" "
call stdvar_string(StdVar_ByValString // char(0)) ! char(0) -> Nulltermination für C
print *, StdVar_ByValString
end program test
I specify the libfile during linking.
But it gets an error:
unresolved external symbol _stdvar_string@4.
(I tested calling the subroutine in the dll from VB,
this works).
How can I get it work, to call it in Fortran correct?
Regards, Astrid
| |
| Anton Haumer 2007-02-12, 7:09 pm |
| Astrid Kuhr schrieb:
>
> Hello!
>
> With my Windowsfortran I want to call a dll/lib,
> which is based on cpp.
>
> program test
> implicit none
>
> interface
> subroutine stdvar_string(StdVar_ByValString)
> !DEC$ ATTRIBUTES DLLIMPORT,STDCALL :: stdvar_string
>
> character(*) :: StdVar_ByValString
> end subroutine
> end interface
>
> character(15) :: StdVar_ByValString
> StdVar_ByValString=" "
>
> call stdvar_string(StdVar_ByValString // char(0)) ! char(0) -> Nulltermination für C
>
> print *, StdVar_ByValString
>
> end program test
>
> I specify the libfile during linking.
>
> But it gets an error:
> unresolved external symbol _stdvar_string@4.
>
> (I tested calling the subroutine in the dll from VB,
> this works).
>
> How can I get it work, to call it in Fortran correct?
>
> Regards, Astrid
It's just the routine name:
the "name decoration" i.e. the "@4" at the end of the name
depends on the specific compiler and the compiler settings.
Consulting your manuals should reveal that details;
either how to influence the name cpp is exporting
or the name fortran tries to import.
HTH Toni
| |
| Astrid Kuhr 2007-02-13, 8:09 am |
| Hello!
Thank you very much. Now with the alias and the change with extern C I
get it
compiling and running. :)
In cpp the string is correct, but the string in Fortran is empty. :(
What is going wrong now there with the string?
This is the Fortran:
program test
implicit none
interface
subroutine StdVar_String(StdVar_ByValString)
!DEC$ ATTRIBUTES DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
character(*) :: StdVar_ByValString
end subroutine
end interface
character(15) :: StdVar_ByValString
StdVar_ByValString=3D" "
call StdVar_String(StdVar_ByValString // char(0)) ! char(0) -
> Nulltermination f=FCr C
print *, "in Fortran:", StdVar_ByValString, "xxx"
end program test
And this the cpp:
//------------------------------------------------------------------------
#include <windows.h>
#include <conio.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"ws2_32.lib") // f=FCr MSV C++
extern "C" void StdVar_String(const char *ByValValue); // (or const
char *s)
//------------------------------------------------------------------------
// Die folgende Funktion unver=E4ndert belassen
BOOL WINAPI DllEntryPoint ( HINSTANCE hDLL, DWORD dwREASON, LPVOID
Reserved )
{
switch (dwREASON)
{
case DLL_PROCESS_ATTACH: { break; }
case DLL_PROCESS_DETACH: { break; }
}
return TRUE;
}
//------------------------------------------------------------------------
extern "C" void StdVar_String (const char *ByValValue)
{
char hostname[255];
char *szIPAddress;
WORD wVer;
WSADATA wData;
PHOSTENT hostinfo;
wVer =3D MAKEWORD( 2, 0 );
if ( WSAStartup( wVer, &wData ) =3D=3D 0 )
{
if( gethostname ( hostname, sizeof(hostname)) =3D=3D 0)
{
if((hostinfo =3D gethostbyname(hostname)) !=3D NULL)
{
szIPAddress =3D inet_ntoa (*(struct in_addr *)*hostinfo-
>h_addr_list);
}
}
WSACleanup();
}
cout<<"in C: "<<szIPAddress<<endl;
getch();
ByValValue =3D szIPAddress;
// strcpy(ByValValue,szIPAddress);
}
//------------------------------------------------------------------------
Regards, Astrid
| |
|
| Astrid Kuhr wrote
Hello!
Thank you very much. Now with the alias and the change with extern C I
get it
compiling and running. :)
In cpp the string is correct, but the string in Fortran is empty. :(
What is going wrong now there with the string?
This is the Fortran:
program test
implicit none
interface
subroutine StdVar_String(StdVar_ByValString)
!DEC$ ATTRIBUTES DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
character(*) :: StdVar_ByValString
end subroutine
end interface
character(15) :: StdVar_ByValString
StdVar_ByValString=" "
call StdVar_String(StdVar_ByValString // char(0)) ! char(0) -
> Nulltermination für C
print *, "in Fortran:", StdVar_ByValString, "xxx"
end program test
Astrid
Try changing the string definition in the API procedure dummy argument to a
character array:
character :: StdVar_ByValString(*)
and put the API call into a procedure of its own (rather than just use an
interface block) where you can put some code to build and decode null
terminated character arrays into normal fortran strings. This is also a good
place of doing any data type conversions between the C and Fortran bits of
your code.
Paul Holden
| |
| Richard Maine 2007-02-13, 7:08 pm |
| Astrid Kuhr <Astrid.Kuhr@googlemail.com> wrote:
> In cpp the string is correct, but the string in Fortran is empty. :(
Just a side matter - not answering your question, but...
What is this cpp you keep talking about? Are you really talking about
the C preprocessor? I suspect that instead, you are talking about the
C++ compiler.
--
Richard Maine | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle | -- Mark Twain
| |
| Anton Haumer 2007-02-13, 7:08 pm |
| Richard Maine schrieb:
>
> Just a side matter - not answering your question, but...
>
> What is this cpp you keep talking about? Are you really talking about
> the C preprocessor? I suspect that instead, you are talking about the
> C++ compiler.
>
In some OS where "+" is not allowed as part of a filename
the executable of a C++ compiler is named cpp ...
So I did guess cpp = C++
Regards,
Toni
| |
| glen herrmannsfeldt 2007-02-13, 7:08 pm |
| Anton Haumer wrote:
> In some OS where "+" is not allowed as part of a filename
> the executable of a C++ compiler is named cpp ...
I believe .cpp is also used as a file extension on
those systems, too. (And, for portability, on others.)
But what is the C preprocessor executable called?
> So I did guess cpp = C++
-- glen
| |
| Craig Powers 2007-02-13, 7:08 pm |
| Astrid Kuhr wrote:
> Hello!
>
> Thank you very much. Now with the alias and the change with extern C I
> get it
> compiling and running. :)
>
> In cpp the string is correct, but the string in Fortran is empty. :(
>
> What is going wrong now there with the string?
>
> This is the Fortran:
>
> program test
> implicit none
>
> interface
> subroutine StdVar_String(StdVar_ByValString)
> !DEC$ ATTRIBUTES DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
> character(*) :: StdVar_ByValString
> end subroutine
> end interface
Check your compiler's documentation to see what the "right" way is to
move strings from one language to another -- I'm quite certain that it's
discussed. One example of the sort of thing you may need to be aware of
is the "hidden length argument". Because of the significance of string
length in Fortran, character strings tend to be non-trivial in multiple
language situations.
| |
| Astrid Kuhr 2007-02-14, 4:12 am |
| Hello!
>What is this cpp you keep talking about? Are you really talking about
>the C preprocessor? I suspect that instead, you are talking about the
>C++ compiler.
Great sorry...
I do not know very much about the C-family.
I thought, that cpp ist the same as c++... (as abbreviation
of c-Plus-Plus...)
Excuse.
Regards, Astrid
| |
| Jugoslav Dujic 2007-02-14, 7:07 pm |
| Astrid Kuhr wrote:
| Hello!
|
| Thank you very much. Now with the alias and the change with extern C I
| get it
| compiling and running. :)
|
| In cpp the string is correct, but the string in Fortran is empty. :(
|
| What is going wrong now there with the string?
|
| This is the Fortran:
|
| program test
| implicit none
|
| interface
| subroutine StdVar_String(StdVar_ByValString)
| !DEC$ ATTRIBUTES DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
| character(*) :: StdVar_ByValString
| end subroutine
| end interface
|
| #include <windows.h>
| #include <conio.h>
| #include <iostream>
| using namespace std;
| #pragma comment(lib,"ws2_32.lib") // für MSV C++
|
| extern "C" void StdVar_String(const char *ByValValue); // (or const
| char *s)
Two (smaller) things:
* You should tell the compiler that StdVar_String uses whatever calling
convention is defined on C++ side (supposedly __cdecl)
* By default, Visual Fortran passes the hidden string length argument
after the string argument, and you should tell the compiler not to do
that:
!DEC$ ATTRIBUTES C,DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
!DEC$ ATTRIBUTES REFERENCE:: StdVar_ByValString
But, the BIG thing (and it wouldn't work even with Fortran-Fortran call)
is... for educational purposes I'll now skip the explanation, and just
advise you to write the interface like this:
interface
subroutine StdVar_String(StdVar_ByValString)
!DEC$ ATTRIBUTES C,DLLIMPORT,ALIAS: "_StdVar_String" :: StdVar_String
!DEC$ ATTRIBUTES REFERENCE:: StdVar_ByValString
character(*), INTENT(OUT) :: StdVar_ByValString
end subroutine
end interface
(Hint: you don't need //char(0) for arguments received by Fortran)
Ah, and the fourth: you DO need:
//ByValValue = szIPAddress;
strcpy(ByValValue,szIPAddress);
--
Jugoslav
___________
www.xeffort.com
Please reply to the newsgroup.
You can find my real e-mail on my home page above.
|
|
|
|
|