I build an application in Borland C++ 6 and I'd like to import external, non Borland library (FFTW, to be exact, http://www.fftw.org).
I have downloaded the fftw dll file, used the implib.exe program to build a lib file known to Borland, included fftw.h in source and copied fftw.h to Borland/include, fftw.lib to Borland/lib and .h, .dll and .lib files to my project folder.
Unfortunately I get several linker errors, which claims:
Unresolved external '{name of the FFTW function}' referenced from {name of the source file}
What do I do wrong?
I'm just telling from a similar story how I managed to get it to work...
There was a DLL that worked (was being sucessfully imported) with Delphi 7, VB.NET and Java. I wanted to make a program with Borland C++ Builder 6 with it. I had the function prototypes and the exact declarations that made the import on those languages. Reasonable?
I thought it would be easy, but I stucked on many dead ends without sucess, with step by step "blind" guides that didn't worked for me. And the IDE or command outputs not helping either.
After a few days I tried (from question 4599357, although the DLL isn't in Visual C++):
using "implib" without "-a" and
having the prototypes declared like this:
extern "C" __declspec(dllimport) __stdcall int someDll_someFunction(someTypes someArgs, ...);
Note that the normal function prototype is at the end. If you have the "normal" prototypes, just add "extern "C" __declspec(dllimport) __stdcall" before them to your source code or header file. :) And I only have functions that return "int", this is why I put "int" there.
I think you're only missing one step... add the .lib file that implib created to your project.
Are you sure that Borland is doing proper name-mangling of the external functions, and that the header has been surrounded with extern "c" {}? And are you sure that Borland is indeed trying to link with the .lib file? Make sure the compiler has the verbose option set.
If that doesn't work, why don't you build FFTW from source instead of using a DLL?
Related
I’m currently having some problems trying to implement an integration with a Verifone PoS.
The bank we are working with provided us with one .dll file, one .h file and one .hpp file.
I’m usually a Java or PHP developer, so for the last days I consumed everything I found on the web about DLL files and how to use them, but none seemed to work so far. I got a lot of errors, many of them being something like “invalid dll”.
I found on the web that alongside a dll file there should have been a .lib file. I asked the third party about this, but apparently
There is no .lib file. The .dll file contains all the required info for an integration
From their documentation of library I found this:
The form of the supplied binary is a dynamic library. By its nature, a dynamic library allows for easier updates and corrections, not requiring recompilation or relinking of the client (calling) code, as long as the procedures prototypes (function parameters and return types) remain the same.
The language used for the library implementation is C++.
To access the functionalities implemented in the library binary, a C-style header interface is provided. This is comprised of the function prototypes available to be called as well as the types of the result-structures through which the returned data needs to be interpreted to make sense for the previously accessed functionality (the specific requested transaction).
So yeah, the .h file includes only the data types, and the .hpp file contains some declarations that looks like this:
extern "C" __declspec(dllexport) bool doSomething(int param);
Also in their documentation there is an example of how an implemetation should look (and it is fairly simple):
bool someVar = doSomething(1);
It looks like those functions can be called as simple as that, but they cannot. If I try to do that I get an “undefined function” (or similar) error.
At this point the only thing that seemed to have somehow worked (maybe) is loading the DLL with the LoadLibrary function. But besides the fact that whatever function I try to call, with whatever parameters, it returns false, it seems kind of wrong that I do not use the .hpp file at all.
So here we are. How I should aproach this? Is there a way to load the DLL and use the provided HPP file as function definitions? If not, is there another way beside LoadLibrary + GetProcAddress combo to do this?
Thank you!
I'm assuming the dll is a native dll, not a managed assembly (.net dll).
Usually, the dll author adds a preprocessor definition to the build system, like DLL_EXPORT. So if the author compiles the dll, the import library (a small .lib file) will contain all functions that used the DLL_API macro. Then the author can ship the very same header to a user. Because that user won't have the DLL_EXPORT macro defined, DLL_API will resolve to a dllimport, which basically says that the annotated function is defined in the import library.
Such a header might look like this (the whole #if condition is usually in its own header file which is then included in all headers that export functions):
#ifdef DLL_EXPORT
# define DLL_API __declspec(dllexport)
#else
# define DLL_API __declspec(dllimport)
#endif
extern "C"
{
void DLL_API SomeFunction(int x);
void DLL_API AnotherFunction(int x);
}
If the author builds the project (in msvc) the compiler will generate the dll file and a small .lib file, which is the import library. This lib will essentially do what you have to do now: calling LoadLibrary and GetProcAddress to resolve all the functions that have been annotated with __declspec(dllexport).
The following part is a bit speculative and I'm guessing a bit here.
All __declspec(dllimport) does, is tell consumers that this dll contains those functions. But the linker has to link a declaration to its definition (implementation) so the function must be defined somewhere at compiletime. And that place is the import library (.lib). If you don't link with the import library, you will get a linker error when you build your project.
This means simply changing the dllexport to a dllimport won't solve your problems. Without an import library your only option is to load the dll manually with LoadLibrary and search for each function.
If I were you, I'd ask the author for an example project that uses the dll. AFAIK, the only ways to use a native dll is either by linking to an import library or by loading everything manually.
Manually generating the import library from the dll
I've tested this to make sure it works.
First of all, fix the header file to either use the macros like I did in the example above, or just use dllimport directly.
Second, open the developer command prompt for VS and follow the steps from this answer. Make sure to use the correct file names and target architecture (x64 or x86). Now you should have a .lib file.
Thrid, add the lib to your project.
Add the directory of the lib (place it somewhere close to the project so you can use relative paths). Open the project properties and follow the steps in this image:
Make sure that Configuration and Platform are correct (you probably want it like in the image). You can also use relative paths. Click on the Macros button to see all predefined paths available to you.
Add the lib to the linker dependencies:
Put the header somewhere in your project where you can access it.
Now you can simply include the header anywhere in your project and use the functions declared inside it. But note that the dll file has to be placed somewhere where LoadLibrary can find it. Preferably this is the same directory where your project's executable is located.
Bonus facts
The definition file (.def) is actually very simple. The def file for my sample code above is:
LIBRARY MyLibrary
EXPORTS
AnotherFunction
SomeFunction
If I remove the extern "C" block around my declarations, my function names will be mangled and the def file looks like this:
LIBRARY MyLibrary
EXPORTS
?AnotherFunction##YAXH#Z
?SomeFunction##YAXH#Z
If you put those functions inside a namespace (for example FooSpace), that namespace name will also be part of the function name:
LIBRARY MyLibrary
EXPORTS
?AnotherFunction#FooSpace##YAXH#Z
?SomeFunction#FooSpace##YAXH#Z
Note that all extern "C" entities will ignore namespaces, meaning all extern "C" functions, variables, types, ... will be put into the global namespace, no matter if you define them inside a namespace or not.
These are also the names that you'd have to pass to GetProcAddress if you did it manually.
I haven't found a solution to my problem, because of limited knowledge about dll Libraries.
I am using Matlab (R2017a) to integrate communication to a device through a dll, which is provided by the manufacturer (files - Xemo-DLL (64Bit) mit Header-Dateien (2.40)).
As far as I understand there is precompiled .dll in C and a header File in C++, beside a VB and VB.NET wrapper.
Question is: What is the best way to integrate the dll into Matlab?
A) I tried loadlibrary(XemoDll). It throws a lot of errors, iostream wasn't found. So I added extern "C" {} to the whole file, which created new errors at every function definition. Where do I have to insert it?
B) I tried to add NET.addAssembly(path\XemoDll.vb) of the VB.NET library. There is a Module with all wrapper functions. Matlabs gives the error "assembly manifest missing" Source: mscorlib.
I found a Tutorial on loading Dlls with the LoadLibrary() command from windows.h, and got it working.
I use a a DllInterface_mex function that gets the function name and calls the approriate function in the Dll.
I'm a real beginner and I'm programming in C++ using Visual Studio.
I've a simple cpp code that recalls some functions written in a .c and .h file. I included that file by means of #include directive and the IDE "sees" the function.
When I compile, I get this
Error 7 error LNK2019: unresolved external symbol _IMUsendAccelToFIFO referenced in function _main D:\Cprojects\Pencil\Pencil\Pencil.obj Pencil
What am I missing here?
Thank you all!
It is a linker error, not a compiler error. The compiler is happy, it saw the declaration of function in the .h file. The linker isn't, it cannot find the definition of the function.
Add the .c file to your project.
If you get an error in Visual Studio you can actually google for the error code and you will get pretty extensive information for that. In this case, googling LNK2019 gives this MSDN page as first hit, which also provides some examples on how you get the error.
Your vendor should have provided some .lib files for you (usually found in a folder named lib?). Make sure that these are added in the project via:
Project > Properties > Configuration Properties > Linker > Input > Additional Dependencies
You could also see if there is any "get started" information for you from your vendor, which explains which dependencies you have to include in your project.
If you feel unsure of what a compiler and what a linker does, pick up a book that explains it, or browse some free alternatives.
Are you using ghettopilot? that's the only reference I can find on the web to the function you're missing. If you are, then you need to include the .lib file for that library in your link options.
Visual Studio will compile .c files as C and .cpp files as C++ by default, and this can cause trouble because if you want to call functions defined in a .c file from a .cpp file, then you must wrap the header in extern "C" { }, as the compiler will expect all functions not declared extern "C" to be from C++. This is because of an implementation detail called name mangling. Alternatively, you could force all files to be compiled as C or as C++ in the project settings.
Solved! Thank you very much!
The libraries I was using needed to be built. I tried but I couldn't build them as I used to get "heap space" error!
I installed Visual Studio 2005 (with which the code was produced by the vendor) and it worked at first attempt! There are probably some back-compatibility issues..
I am importing an C++ DLL in an Inno Setup install script. The DLL code is as follows:
void __stdcall SetFbParam(
char *dbFileName,char *dbTableName,char *dbParamName,char *dbParamValue) {
// of no use here and doesn't change anything
}
In the Inno Setup, I import it using
procedure FBset(dbFileName,dbTableName,dbParamName,dbParamValue: String;);
external 'SetFbParam#files:MyDll.dll stdcall setuponly';
However, I always get a runtime error during launch of the installer, saying that it cannot import my dll. I tried it with various calling conventions, but it always fails.
If it's of any importance, I'm running Win7 x64 with UAC on (the installer requests rights elevation and crashes after that).
The exact message is:
Error
Runtime error (at -1:0):
Cannot import
dll:C:\Users\Nevod\AppData\Local\Temp\is-6LOEC.tmp\MyDll.dll
The dll is there.
Thanks!
Is MyDll.dll 32-bit?
Does MyDll.dll depend on any other DLLs in the same directory? If so, you need to list the name(s) of those DLLs after MyDll.dll to ensure that they are extracted before MyDll.dll is loaded, and you likely need the loadwithalteredsearchpath option as well. Example from the help:
procedure ADllFunc(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal);
// A.dll depends on B.dll
external 'ADllFunc#files:A.dll,B.dll stdcall loadwithalteredsearchpath';
(I know it is old but maybe some other hits this one too)
Most probably the name of the function is mangled in the C++ DLL. I had the same problem and I was able to solve it by recompiling the dll. In short:
If you export from C++ something like:
void __stdcall foo()
you will get a function called (Visual Studio):
?foo##YGXXZ
To prevent name mangling you should use extern "C" directive. Example (Visual Studio)
extern "C" __declspec( dllexport ) void __stdcall foo()
However I have found that Visual Studio will continue to mangle and you get something like:
_foo#0
The sole way I was able to get clean names is explained here:
C++ DLL Export: Decorated/Mangled names
And the culprit is indeed __stdcall. If you remove that from your declaration:
extern "C" __declspec( dllexport ) void foo()
you will again get a clean export, even without a DEF file. IMO this should be good enough, as the code above declares a "C" exported function and the default calling convention for C is stdcall. However I haven't had the time and disposition to validate this as adding a DEF file is way easier than navigating asm code and check stack pointers :)
In order to use DLLs in Inno Setup's [Code] section please make sure:
DLL is in 32 bit mode (even if the installer is built for 64bit and is running in 64bit mode)
exported functions have
extern "C" __declspec( dllexport )
modifier
use cdecl calling convention because stdcall mangles name (https://learn.microsoft.com/en-us/cpp/cpp/stdcall). Of course it is possible to specify mangled name in Inno Setup import statement. But it seems easier to just use cdecl.
As mentioned in other answers, do not forget to embed all dependencies of your DLL. Though if it is your DLL, better might be to get rid of (or at least reduce) the dependencies.
For example when building C++ DLL in Visual Studio, link the runtime statically, not dynamically.
In project Properties, go to C/C++ > Code Generation > Runtime Library and select Multi-threaded (not DLL).
There are also tools that can embed other external dependencies.
See Embedding DLLs in a compiled executable
Update: I get this warning when compiling: multiple '.text' sections found with different attributes
Hi,
I've compiled some libraries (.a and .dll) in Linux using the MinGW Cross Compiler. I can successfully link against them (.a) in Visual Studio 2008. However, when it runs (using .dll), it terminates with the address pointer pointing at empty memory addresses.
Is there a way/a list of things to do that will allow me to use those libraries successfully in VC08?
The cross compiler generates
*.dll.a
*.dll
Thanks
Found it.
http://www.mingw.org/wiki/MSVC_and_MinGW_DLLs
You have to have a def file and use the VC's lib tool to generate an import library.
It sounds to me like the two parties are not using the same calling convention, meaning there is a problem in the way the exported dll functions have been defined.
By far the simplest approach would be to define the functions as extern "C" by defining the exported functions as follows:
extern "C"
{
int MyExportedFunction(char *buffer, int length);
void MyOtherFunction();
};