Calling a dll from fortran - dll

I am aiming at calling a dll file from a fortran compiler. I am doing all this in windows using the mingw compiler.
The dll was created using a g++ compiler
The code for which I am trying to create a dll
// example_dll.cpp
#include <stdio.h>
#include "example_dll.h"
__stdcall void hello()
{
printf("Hello");
}
command entered in the command prompt
g++ -c -DBUILDING_EXAMPLE_DLL example_dll.cpp
g++ -shared -o example_dll.dll example_dll.o -Wl,--out-implib,libexample_dll.a
The above two commands creates the dll file.
The job now is to create a fortran script to compile the dll file previously created.
For this purpose I am looking forward to create a fortran file capable of linking to the dll previously created.
Any help will be appreciated.
Thanks,
Adarsh

Later I tried some of the possibilities. My updated files are as follows
C file for which the DLL is created is as follows
// example_dll.c
#include <stdio.h>
#include "example_dll.h"
EXPORT void tstfunc (void)
{
printf("Hello\n");
}
EXPORT int Double11(int x)
{
printf("From the Double11\n");
printf("%d\n",x);
return x;
}
.h file used to create the DLL is as follows
// example_dll.h
#ifdef EXAMPLE_DLL_H
// the dll exports
#define EXPORT __declspec(dllexport)
#else
// the exe imports
#define EXPORT __declspec(dllimport)
#endif
// function to be imported/exported
EXPORT void tstfunc (void);
EXPORT int Double11(int x);
Fortran file used to link the dll is as follows
! fortcall.f90
program ForCall
IMPLICIT NONE
integer :: sum
integer :: inte3
INTERFACE
SUBROUTINE write() BIND(C,NAME='tstfunc')
END SUBROUTINE write
END INTERFACE
INTERFACE
SUBROUTINE get_integer(inte,inte2) BIND(C,NAME='Double11')
USE ISO_C_BINDING
IMPLICIT NONE
INTEGER (C_INT), VALUE :: inte
INTEGER (C_INT), INTENT(OUT) :: inte2
END SUBROUTINE get_integer
END INTERFACE
CALL write
CALL get_integer(1,inte3)
print*,"the output is",inte3
END PROGRAM ForCall
After entering the following directive in the command prompt
gfortran -o dll_foo_test fortcall.f90 -L. example_dll.dll
The output will be as follows
Hello
From the Double11
1
the output is -2
At this point something is not right. The code is capable of passing a value from FORTRAN to the DLL, whereas the code is not returning the right value from the dll. Some junk value of -2 is being displayed instead of 1.
I would like to fix that part in the code.

Related

How can Poplar codelets include code from other header files?

Is it possible for codelets to reference code in other files, like header files?
If I have a codelet file
//FileA.cpp
#include "FileB.h"
class SomeCustomVertex : public Vertex {
public:
bool compute() {
int a = SomeConstantDefinedInFileB;
}
...
}
and some other "codelet" file
//FileB.h
const int SomeConstantDefineInFileB = 42;
and in the host graph program:
graph.addCodelets({"codelets/FileA.cpp", "codelets/FileB.h"});
I get a compile error from popc:
fatal error: 'FileB.h' file not found
#include "FileB.h"
^~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
terminate called after throwing an instance of 'poplar::graph_program_compilation_error'
what(): Codelet compilation failed (see compiler output for details)
I figured this out.
Graph::addCodelets has a parameter StringRef compileFlags = "", which you can use to inject compiler options.
popc --help shows an option
-I arg Add directory to include search path
So when I use graph.addCodelets({"codelets/FileA.cpp"}, "-I codelets"); in the host program, and have my codelets in 'codelets' subdirectory, this works. No need to explicitly list the ".h" files in the arguments.
Incidentally, also a good way to ensure compiler optimisation (-O3) for the custom codelets.

CMake adds -Dlibname_EXPORTS compile definition

CMake adds the following compile definition to all source code files automatically when simply compiling a target:
-Dlibname_EXPORTS
Why is this done and how can I disable it?
cmake add <libname>_EXPORTS macros only for shared libraries. It's useful when exporting API's in Windows DLL.
#if defined(_WINDOWS) && defined(testlib_EXPORTS)
# define API_DLL extern "C" __declspec(dllexport)
#else
# define API_DLL
#endif
API_DLL void foo();
It could be disabled by setting the DEFINE_SYMBOL property of target to empty.
# disable the <libname>_EXPORTS
set_target_properties(sharedlib
PROPERTIES
DEFINE_SYMBOL ""
)
Reference
http://www.cmake.org/cmake/help/v3.0/prop_tgt/DEFINE_SYMBOL.html

How to make a loadable dll to use tcl code functionality by any program

I have created a GUI using tcl. I want to make some of the core functionalities of the tcl code available to be used by any program which supports dll. For that i have taken a very simple tcl code example, which adds two integer numbers and i have written a c wrapper function to use this functionality. This is working for me. Now how can i create a dll for these two c and tcl files, so that any program can use this addition functionality by simply loading the dll.
Here is my simple tcl code :
/* Filename : simple_addition.tcl */
#!/usr/bin/env tclsh8.5
proc add_two_nos { } {
set a 10
set b 20
set c [expr { $a + $b } ]
puts " c is $c ......."
}
And here is my c wrapper function which uses the above tcl addition functionality :
#include <tcl.h>
#include <tclDecls.h>
#include <tclPlatDecls.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char **argv) {
Tcl_Interp *interp;
int code;
char *result;
printf("inside main function \n");
Tcl_FindExecutable(argv[0]);
interp = Tcl_CreateInterp();
code = Tcl_Eval(interp, "source simple_addition.tcl; add_two_nos");
/* Retrieve the result... */
result = Tcl_GetString(Tcl_GetObjResult(interp));
/* Check for error! If an error, message is result. */
if (code == TCL_ERROR) {
fprintf(stderr, "ERROR in script: %s\n", result);
exit(1);
}
/* Print (normal) result if non-empty; we'll skip handling encodings for now */
if (strlen(result)) {
printf("%s\n", result);
}
/* Clean up */
Tcl_DeleteInterp(interp);
exit(0);
}
This c wrapper is working fine for me and gives correct results.
Now I want to create a dll file, so that if i include that dll to any program that supports dll, it should be able to use this addition functionality of the above tcl code. Can anybody please tell me the way i can do it. Please help me. I am new to this dll concept.
In order to create the .dll you'll have to use something like Visual Studio and C or C++ to create the .dll (there are lots of other tools out there that can create .dll files but VS is easy to get hold of and to use.) So in VS create a new project, this needs to be a C++ WIN32 project. Select the DLL application type and the Export Symbols additional option.
VS will create a basic .dll that you can then amend to do what you want. I short I'd look at putting the creating/destruction of the intrepter into the dllmain:
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
Tcl_FindExecutable(NULL);
interp = Tcl_CreateInterp();
}
case DLL_THREAD_ATTACH:
break ;
case DLL_THREAD_DETACH:
break ;
case DLL_PROCESS_DETACH:
{
Tcl_DeleteInterp(interp);
break;
}
}
return TRUE;
}
and then create functions exported by the .dll that make use of the interpreter. If you aren't familiar with the concept of shared libaries then I'd suggest spending a little time reading up on them, try here and here for some background reading.

error when compile lex.yy.c with g++

i have written a bison, flex and c++ files.
Compilation of bisoon and flex was passed. But when i'm trying to compile the c and cpp files:
g++ *.cpp *.c, i get strange error:
lex.yy.c:479: error: expected `;' before "static"
and when i opened lex.yy.c file, i see code that was automatically created by flex. This is some part of code around line 479, line 479 is bold:
using namespace std;
using namespace output
#line 465 "lex.yy.c"
/* Macros after this point can all be overridden by user definitions in
* section 1.
*/
#ifndef YY_SKIP_YYWRAP
#ifdef __cplusplus
extern "C" int yywrap YY_PROTO(( void ));
#else
extern int yywrap YY_PROTO(( void ));
#endif
#endif
#ifndef YY_NO_UNPUT
static void yyunput YY_PROTO(( int c, char *buf_ptr ));
#endif
#ifndef yytext_ptr
static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int ));
#endif
i don't have any idea what to do. Please help me.
thanks
You should`t try to fix the error in file generated by lex, instead of it you need to check your lex specification for errors.
UPDATE:
Possible place to look for source of such mistake is lex specification user code section. As it is noticed in comments, LEX isn`t checking code that it generates from the specification.

How to create dll using gcc compiler/Mingw for visual basic?

How to create dll using gcc compiler/Mingw for visual basic?
The following is how I was able to get MinGW to build a DLL to be used in Excel 2003 VBA.
fooBar.cpp
int __stdcall Foo(int x)
{
return x * x;
}
double __stdcall Bar(double x)
{
return x * x;
}
1) Start MinGW shell and create a directory called fooBar .
Close the Excel Workbook (if open).
mkdir -p fooBar
cd fooBar
rm *.a *.dll *.def
2) Compile and generate a .def file - Note: this dll will not work because it has mangled symbols.
gcc -shared -o fooBar.dll fooBar.cpp -Wl,--output-def,fooBar.def,--out-implib,libfooBardll.a
The generated fooBar.def will look something like:
EXPORTS
_Z3Bard#8 #1
_Z3Fooi#4 #2
3) Modify the generated fooBar.def file by adding clean symbol aliases for the generated symbols. fooBar.def should now look something like:
EXPORTS
_Z3Bard#8 #1
_Z3Fooi#4 #2
Bar = _Z3Bard#8
Foo = _Z3Fooi#4
4) Cleaup again (except for the modified fooBar.def)
rm *.a *.dll
5) Compile with .def file with clean symbol aliases for the generated symbols.
gcc -shared -o fooBar.dll fooBar.cpp fooBar.def -Wl,--out-implib,libfooBar_dll.a
6) Open Excel and add the following VBA code (make sure to use the proper path, doubt it will have mmorris in it):
Private Declare Function Foo Lib _
"C:\MinGW\msys\1.0\home\mmorris\fooBar\fooBar.dll" _
(ByVal x As Long) As Long
Private Declare Function Bar Lib _
"C:\MinGW\msys\1.0\home\mmorris\fooBar\fooBar.dll" _
(ByVal x As Double) As Double
7) If you want to call the functions from an Excel Workbook, in a cell type =Foo(5) or =Bar(5)
First some DLL-iquette:
All exported function should have C linkage.
All C++-exceptions thrown inside the DLL should be catched inside the dll.
Why? Because there is no standard C++ ABI on Windows.
Also use __declspec(dllexport) on functions that should be exported
Now how to make the DLL without needing any DEF file
fooBar.cpp
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) int __stdcall square_int(int x) //I prefer manual mangling in this case to support static polymorphism
{
return x * x;
}
__declspec(dllexport) double __stdcall square_double(double x)
{
return x * x;
}
#ifdef __cplusplus
}
#endif
compile using
gcc fooBar.cpp -shared -Wl,--kill-at -o fooBar.dll
Now you should be able to call square_xxx as in mmorris answer. His solution probably works though.
This: http://www.mingw.org/wiki/DLL might be useful to you.
VB (all versions) prefers the pascal calling convention.
Declare your external functions with WINAPI and export them in your .def file.