- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I want to use a DLL file that I created in Fortran using ifort in a C++ program I don't know how to do it on the C++ side so far I have
subroutine func01( a ) bind(C,name="func01")
!DEC$ ATTRIBUTES DLLEXPORT :: func01
implicit none
character(len=1), dimension(90) , intent(in) :: a
character(len=30), dimension(3) :: b
integer*4 :: count,i,j
count=1
do j=1,3
b(J)=''
do I=1,30
b(J)=trim(b(J))//a(count)
count=count+1
enddo
enddo
print *
print *, "char length = ", len(b(1)), len(b(2)), len(b(3))
print *, "raw a(1) : [", b(1), "]"
print *, "raw a(2) : [", b(2), "]"
print *, "raw a(3) : [", b(3), "]"
print *, "trim : [", trim(b(1)), "] [", trim(b(2)), "] [", trim(b(3)), "]"
end
and on the c++ side I have been able to gather the following code
str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";
for( int k = 0; k < numstr; k++ ) {
memset( a
str
}
// func01( a[0], lenmax );
// func01( a[1], lenmax ); // pass from mercury
HINSTANCE hDLL = LoadLibrary("foo.dll");
if (hDLL == NULL)
{
std::cout << "Failed to load library.\n";
}
else
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "func01");
FreeLibrary(hDLL);
}
lpfnDllFunc1( a[0], lenmax );
// std::cin.get();
return 0;
}
When I compile the program and run it it crashes. I am sure that I am making some errors on the C++ side of thing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found the solution myself. The following code works properly the trouble I was having was have with was how the Fortran DLL was being compiled I used MSV 2008 environment to compile the dll now everything works okay.
#include <iostream>
#include <Windows.h>
typedef void(*LPFNDLLFUNC1)(char *c, const int len);
int main()
{
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
const int lenmax = 30, numstr = 3; // changed char length to 30 to fit in the terminal
char a[ numstr ][ lenmax ];
std::string str[ numstr ];
str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";
for( int k = 0; k < numstr; k++ ) {
memset( a
str
}
HINSTANCE hDLL = LoadLibrary("DLL1.dll");
if (hDLL == NULL)
{
std::cout << "Failed to load library.\n";
}
else
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "func01");
lpfnDllFunc1( a[0], lenmax );
}
FreeLibrary(hDLL);
return 0;
}
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
As explained in the comments on your post on StackOverflow, you are calling FreeLibrary before you reference the function. That FreeLibrary call may unload the DLL from memory - the Fortran procedure will no longer be available to call. Move the FreeLibrary call to after the reference to the Fortran procedure.
You should also check the return values from the GetProcAddress call to make sure that the DLL contains the procedure with the expected name.
The Fortran subroutine takes a single argument. Your C++ code passes two arguments.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
HINSTANCE hDLL = LoadLibrary("source1.dll");
if (hDLL == NULL)
{
std::cout << "Failed to load library.\n";
}
else
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "func01");
}
//lpfnDllFunc1( a[0], lenmax );
FreeLibrary(hDLL);
// std::cin.get();
I fixed that with the above but I am getting a "Failed to load library." i.e. the library does not load.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am using the following to build my files
ifort /nologo /iface:stdcall /libs:dll /threads /c source1.f90
link /NOLOGO /SUBSYSTEM:WINDOWS /manifest /dll /out:source1.dll source1.obj
Creating library source1.lib and object source1.exp
cl /EHsc main1.cpp
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Why are you specifying stdcall in just 1 place? CL defaults to cdecl, same as ifort does. One would expect a link error. Then you would add the .dll to your final build step.
As far as I know, the only current use for stdcall is in windows api calls, and the current ifort provides for that by allowing the corresponding attributes along with bind(c...).
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I found the solution myself. The following code works properly the trouble I was having was have with was how the Fortran DLL was being compiled I used MSV 2008 environment to compile the dll now everything works okay.
#include <iostream>
#include <Windows.h>
typedef void(*LPFNDLLFUNC1)(char *c, const int len);
int main()
{
LPFNDLLFUNC1 lpfnDllFunc1; // Function pointer
const int lenmax = 30, numstr = 3; // changed char length to 30 to fit in the terminal
char a[ numstr ][ lenmax ];
std::string str[ numstr ];
str[0] = "moon"; str[1] = "mercury"; str[2] = "jupiter";
for( int k = 0; k < numstr; k++ ) {
memset( a
str
}
HINSTANCE hDLL = LoadLibrary("DLL1.dll");
if (hDLL == NULL)
{
std::cout << "Failed to load library.\n";
}
else
{
lpfnDllFunc1 = (LPFNDLLFUNC1)GetProcAddress(hDLL, "func01");
lpfnDllFunc1( a[0], lenmax );
}
FreeLibrary(hDLL);
return 0;
}
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page