Function is declared, but not defined in shared library - c++

I have a source code of some library. There is a function that is only declared (in a header file), but not defined in the source code.
extern "C" {
extern int theFunc(int);
}
What is the reason to have only a declaration of a function in a library?

In addition of Mike Kinghan's answer (which covers most of the cases), there is also a (rather unusual) reason to declare in the library header file a function not implemented in that library. Sometimes, that library expects a plugin and the user is expected to provide such a plugin (in some way, perhaps passing the plugin file name to some other function). The library would use dynamic loading techniques (such as dlopen(3) on Linux) to install such a plugin. And it would fetch some particular function (with dlsym(3) on Linux) from the plugin. Then it makes sense to declare, but not define such a plugin function, in the library headers.
I do admit that this case is unusual and contrived.
For a concrete example, read about GCC plugins. Your plugin should #include "gcc-plugin.h" which indirectly declares
/* Declaration for "plugin_init" function so that it doesn't need to be
duplicated in every plugin. */
extern int plugin_init (struct plugin_name_args *plugin_info,
struct plugin_gcc_version *version);
but that plugin_init should be defined by your plugin code. Then GCC would dlopen your plugin, using something equivalent to
void*plhdl = dlopen("/home/you/yourplugin.so", RTLD_NOW);
and later get a function pointer using
typeof(plugin_init)* funptr = dlsym(plhdl, "plugin_init");
Notice that the symbol plugin_init does not appear in the code segment of GCC.
Another example is the Qt framework (a set of libraries). Read about Qt plugins.

Related

How to use a provided DLL file with HPP header?

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.

Making C++ library without name mangling with MinGW

I have several C++ classes which I decided to compile into separate library usable by other applications. Therefore I made a simple C-compatible envelope which wraps C++ classes. The function definitions in the header file are put in extern "C" block.
When I compile this using MinGW g++, I get shared library with decorated function names. Each function name has suffix #ars_size. To get rid of this names I passed -Wl,--kill-at argument to g++. Then I finally got undecorated names.
Then I made a simple C++/Qt application which serves as a tester of the new library. Unfortunately when I include the library's header file into my C++ application, I get linking errors:
release/mainwindow.o:mainwindow.cpp:(.text+0xd6f): undefined reference to `_imp__TdbGetLastErr#12'
release/mainwindow.o:mainwindow.cpp:(.text+0x1163): undefined reference to `_imp__TdbGetAsyncErr#12'
release/mainwindow.o:mainwindow.cpp:(.text+0x166f): undefined reference to `_imp__TdbStop#4'
release/mainwindow.o:mainwindow.cpp:(.text+0x1698): undefined reference to `_imp__TdbForceTrigger#0'
...
To get rid of these errors I have to exclude -Wl,--kill-at during compiling of the library. But then the library is not compatible with C applications. I believe the key is to make MinGW g++ to link undecorated functions. Please does anybody know, how to do this?
EDIT: Adding more details requested in comments.
When compiling the library, I include its header (with extern "C") from the
source code, so the compiler should be aware of extern "C".
The library is not so simple wrapper. Actually it creates several C++ objects
which are operated using handles from C applications. Also it catches
exceptions from C++ classes etc.
Klasyc

C++ Plug-in Version Checking via Function Export

I have two DLLs, Core and Extension. Extension implicitly links Core (using Core.lib). Extension is intended to be a plug-in (explicitly linked) into an executable which also implicitly links Core.
Core declares a function which is exported in Core.dll (extern "C" __declspec(dllexport) int GetCoreVersion()), which I would also like to export in Extension.dll.
The intended purpose is to compare versions--I want to be able to ensure that the plug-in (Extension) was linked against the same version of Core.dll as the executable. This check would be performed in the executable, as it explicitly links Extension.dll (via LoadLibrary and GetProcAddress). Is there a better way?
I added the following to Extension, which causes the GetCoreVersion symbol to be exported:
#pragma comment(linker, "/export:_GetCoreVersion");
The executable is now able to find the function (via GetProcAddress("GetCoreVersion")).

JNI and the library it links to

I searched but did not find an answer to this "problem". Basically, one usually needs to include the jni.h header to access jni functions, but the header contains mostly function prototypes and struct declarations, so we either include the sources to resolve the functions or include a static or dynamic library(none found so far) so the linker can resolve the function prototype declarations.
I have so far used the Android NDK to build a native library and all I did was include the jni.h header to use jni functions, but even on Oracle's documentation and examples all they do is include the jni.h header and specify include directories to the compiler, so how does the compiler find the implementations?
how does the compiler find the implementations?
The compiler doesn't have to find the implementations, the JVM tells you where they are dynamically:
JNIEnv is a typedef for the struct JNIEnv_. That struct contains a const struct JNINativeInterface_* called functions and many methods. If you take a look at the JNI documentation you will notice that most methods have a JNIEnv* as their first argument, however you call them with env->method(...), without the JNIEnv* argument. The methods from the documentation are the actual methods and pointers to them are in functions in JNIEnv_. The methods in JNIEnv_ are wrappers that simply call the method-pointers in functions. Whenever the JVM creates a JNIEnv_ and the corresponding JNINativeInterface_, it dynamically writes all the method addresses.

problem wrapping extern "C" library in a namespace

I am using a C library (libgretl) from C++ and some of its functions conflict with my code, so I wanted to wrap it in a namespace, like this:
namespace libgretl {
extern "C" {
#include <gretl/libgretl.h>
}}
However, this does not compile, I get "undefined" errors from gcc files (using mingw32 with gcc 4.5.2 on Windows).
The first errors come from the following code block of file c++/cstddef:
_GLIBCXX_BEGIN_NAMESPACE(std)
using ::ptrdiff_t;
using ::size_t;
_GLIBCXX_END_NAMESPACE
where the macros expand respectively to namespace std { and }. There are more errors after these.
Omitting the extern "C" directive does not help. Using an anonymous namespace reduces the amount of errors, but it still won't compile.
My question is therefore if there is some way to include such a C library and place its functions into a namespace, without changing the gcc or the library's source files?
Thanks.
Michal
You can't do it. Namespaces are not just source code decorations, they are mangled to object symbols by compiler.
Native C function foo() in library will be available by symbol _foo in object file, but calling bar::foo() will generate reference to, for example, #N3barfoo. As result, linker error will occur.
You may create "proxy" functions in separate source file, including original library header only in this source and putting all proxy functions to namespace.
You don't get to simply wrap a namespace around an external declaration and have it appear within that namespace... the item (function, global) must have been built within that namespace from the start. Since C doesn't support namespace resolution, this could not have been the case.
You need to change your own code to accommodate this library, unless you're willing to chante the library itself.
In order to refer to a non-namespace'd item that conflicts with your own namespace'd item, refer to ::item().
I guess the C library was compiled as C, which means namespaces are not included and not supported in the compiled code. Thus, your compiled C library cannot be in a namespace. Altering the header by encapsulating the include will not change that.
You can still encapsulate your own code in a namespace.