I have to use an ugly C-library inside my c++ application. In the following explanation I will call it UglyLib. I successfully compiled UglyLib as a statically linked library.
In the file ugly.h UglyLib uses an extern variable:
file ugly.h:
extern SomeStruct_type somestruct;
the variable is defined (and also used) in another file. I will call it anotherugly.c.
file anotherugly.c:
SomeStruct_type somestruct;
My c++ application is based on a generic template library (TemplateLib) and the application itself is composed by the main window GUI code and on an application library statically linked with the main window code. I will call this statically linked library ApplicationLib.
TemplateLib contains a templatelibfile.h, that exports a function foo using somestruct, the extern variable exposed by UglyLib.
file templatelibfile.h:
#include<ugly.h>
...
void foo()
{
...
do something with somestruct
...
}
foo function is used by appllibfile.h contained in the statically linked ApplicationLib.
file appllibfile.h:
#include<templatelibfile.h>
...
void applfoo()
{
...
foo();
...
}
Main Window application includes appllibfile.h
file main.cpp:
#include<appllibfile.h>
...
int main()
{
...
applfoo();
...
return 0;
}
In VS2008 when I try to compile the main window application, the microsoft linker give me this error
error LNK2001: unresolved external symbol "struct SomeStruct_type somestruct" (?somestruct##3USomeStruct_type##A)
If I add in templatefile.h a new definition of the extern variable the compiler stops to complain.
file templatelibfile.h:
#include<ugly.h>
SomeStruct_type somestruct
...
void foo()
{
...
do something with somestruct;
...
}
BUT I would wish to avoid it because I don't know if it is the correct thing to do (I don't want to risk to alter the semantic of UglyLib redefining a different instance of somestruct variable).
Have you some suggestions in order to avoid the linking problem without redefining the somestruct extern variable?
Thanks a lot!
It's probably because of the name-mangling that the C++ compiler does. Since anotherugly.c is a C source (presumably compiled with a C compiler), the symbol somestruct will be exposed without being mangled. When you compile the rest of the files with a C++ compiler, the linker then looks for a mangled name which does not exist.
I think surrounding the declaration in ugly.h in extern "C" might solve the problem.
Related
We build a static library with Visual C++ (version 15 is used), and this library that has the following functions:
extern "C" void __stdcall Internal()
{
...
}
class SomeClass {
inline void SomeFunc()
{
Internal(); // calling Internal here
}
}
When this static library is linked to an EXE, Internal gets exported from the EXE (i.e., one can see Internal in the EXE's exports). If we make SomeFunc not inline, Internal doesn't get exported.
Does anybody know why the "inline" modifier has an effect of an undesired export being generated?
I have a main application EXE "main.EXE". I've created a global pointer in a header file globalf.h with extern like:
globalf.h
extern SomeClass* cPtr;
Now in Main.EXE code
#include globalf.h
INitialize()
{
cPtr = new SomeClass(); // works fine.
D.DLL:
#include "globalf.h"
void DllFunc()
{
cPtr->someFunction1(); // link error unreslved external symbol.
I'm not able to access the global pointer variable in DLL code, even
though I had declared inMain.EXE code.
I know this declaration in main.EXE's Initialize() isn't visible to
DLL. But how do I achieve this? Is there a way in C++ for handling
such globals across DLL & EXEs.
Instead of exporting a global pointer variable, I'd pack it and other variables you need to share between the EXE and the DLL in a structure, and then pass a pointer to that structure as a function parameter for example to a DLL initialization function.
// Function exported from the DLL.
// Called by the EXE during initialization.
//
// The DLL receives a pointer to the global state structure,
// shared between the EXE and the DLL.
//
BOOL YourDllInit(GlobalStuff* pGlobal);
I'm trying to use opencv C++ library with another lib in C. So I've defined a structure in an .hpp file which I've added to the .h of the C library
typedef struct {
cv::FileStorage fs;
cv::Mat mat;
} myCPPStruct;
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
myCPPStruct * mycppstruct;
} myCStruct;
void initialize_myCPPStruct(myCPPStruct * mycppstruct);
#ifdef __cplusplus
}
#endif
In the .c files the initializer for myCStruct calls initialize_myCPPStruct which is defined in a .cpp file somewhat as:
void initialize_myCPPStruct(myCPPStruct * mycppstruct){
mycppstruct = {};
mycppstruct->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
mycppstruct->mat = cv::Mat(3,3,CV_8UC3);
}
But once it tries to allocate a value to mycppstruct->fs, it gets a segmentation fault. I assume this is because there is no memory allocation in C, but I've tried
std::memset(stitcher->fs,0,sizeof(cv::FileStorage));
which also doesn't work as it can't parse cv:FileStorage as void *.
Will I have to use the deprecated C OpenCV library to make this work?
EDIT - More details about the compilation.
For the C lib, I recompile (without linking ie with the -c option)all the .c files where I've added C++ functions or structures using g++ while making sure I add the __cplusplus guards in the .h files. All the .c files without C++ code already have .o files compiled with gcc. I then compile the whole program with g++ while making sure to include the relevant library files. There are no compiler errors.
It seems the structure itself has not been created.
You might try this (or something similar):
myCPPStruct* initialize_myCPPStruct()
{
myCPPStruct* result;
result = new myCPPStruct();
result->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
result->mat = cv::Mat(3,3,CV_8UC3);
return (result);
}
You need to allocate the memory for your structure:
myCPPStruct = malloc(sizeof(myCPPStruct));
Use the above line instead of:
mycppstruct = {};
Also,since your function is passing in the pointer and allocating the memory internally you need to pass a pointer to the pointer or the allocation will not be passed back:
void initialize_myCPPStruct(myCPPStruct** mycppstruct){
if ( mycppstruct == NULL ) {
//Abort as no address of the pointer to allocate passed
return;
}
*myCPPStruct = malloc(sizeof(myCPPStruct));
(*mycppstruct)->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
(*mycppstruct)->mat = cv::Mat(3,3,CV_8UC3);
}
Or you could just change the above to:
myCPPStruct* initialize_myCPPStruct(void) {
myCPPStruct* ptr = malloc(sizeof(myCPPStruct));
ptr->fs = cv::FileStorage( "file.txt", cv::FileStorage::READ );
ptr->mat = cv::Mat(3,3,CV_8UC3);
return ptr;
}
First, let me point out the sentence which confuse me.
there is no memory allocation in C
Yes, there is. Have a look to malloc function.
char *my_allocated_string = malloc(sizeof(char) * 42);
Here you are, you've allocated an array of character of size 42.
Now, have a look to : mycppstruct = {};
That's not how you allocate a structure in C. You have to call... malloc() !
my_struct *s = malloc(sizeof(my_struct));
s->fs = 42;
Ok. Done. Feels better.
Well, first of all, you have to create a wrapper around your C++ code. Why ? Because C++ allows multiple definition of a given function (also call symbol) :
int my_func(int);
int my_func(char);
This is valid in C++. But, think about it, how is the compiler able to let two functions with the same name exist ? Well it's not. It uses a technique named mangling when evaluating the functions to create 2 different names. Mangling is use on everything function and method. Event on single functions.
C is not able (and willing) to create several functions with the same name. Otherwise, you will experience a kind of function-already-implemented error. When you declare :
int my_func(int);
the C compiler will create the symbol : my_func. No mangling.
To make both language interact, you need to reference to a symbol understandable by the C compiler. If you call my_func from a C source file, the C compiler will look for my_func symbol. Bu since C++ will modify its my_func symbol into something like _ZN9myfuncE, the linkage will fail. That's why you have to says to the C++ compiler to not use mangling on the function you expose to C. That's why you need extern "C" { }.
Feeww, so far so good...
Now you have to embed you C API into an extern "C" block :
In my_c_api.h :
void my_func(int);
void my_func(char);
In my_c_api.cpp :
#include "my_c_api.h"
extern "C" void my_func_i(int i) { my_func(i); }
extern "C" void my_func_c(char c) { my_func(c); }
You compile it to create your C++ library.
In your C compilation pipeline, you link against your new C++ library and header files. Then :
#include "<path_to_my_c_api.h>"
void c(int i,char s)
{
my_func_i(i);
my_func_c(c);
}
You cannot compile C++ code with C compiler. You have to compile te C++ code independently.
More on ISO CPP.
I've project where I need to distinguish files belongs to linux daemon (witten in C) and simple linux program (written in C++). Those two projects used 2 shared files (helpers_functions). Daemon and program has different logging system. Daemon write to file, program to stdout.
Problem occurs when I want to log something in common functions for both programs (inside helper_functions file). I don't want to pass via parameter, that this is program A, or program B.
I've compile files belongs to separate programs with g++ flag -D, but what can I do, when I want to log from common files? I cannot define there anything, because I don't know when I use it for program A, or when for program B.
You could add a global variable
const int iamprogram = ...;
which is defined to be PROGRAM_A in program A and PROGRAM_B in program B to solve the immediate problem. You could also make this variable directly contain the file you want to log to:
const char *program_logfile = "/path/to/logfileA";
In the long run, I suggest you to refactor your code such that the common code doesn't depend on which program it is part of. That's much more maintainable and expandable for the case where you want to use the code for a third program as well.
I'm not 100% sure if runtime dynamic linking can handle this. It would definitely work if you statically link the helper functions into each executable.
Provide a logging function with the same API in both programs. Have the library functions that want to log something call this function. They get the implementation provided by the program that's using the library.
Header file included by each program, and by the library
// common_log.h
#ifdef __cplusplus
extern "C" // for the following definition only, no opening {
#endif
// used by code that can be part of either program
void common_log(char *msg, int log_prio);
Implementation in the tty C++ program (simple logging):
#include "common_log.h"
#include <iostream>
// used by the rest of the C++ program
void simple_logger(char *msg) {
cerr << msg;
}
extern "C" void common_log(char *msg, int log_prio) {
simple_logger(msg);
}
Implementation in the daemon C program:
#include "common_log.h"
#include <stdio.h>
#include <errno.h>
static FILE *logfp;
static int log_level;
// used by daemon code
void fancy_logger(char *msg, int log_prio) {
if (log_prio < log_level)
return;
if (EOF == fputs(logfp, msg)) {
perror("failed to write log message to log file: ");
}
}
// or use linker tricks to make common_log an alias for fancy_log,
// if they both have the same signature and you don't need to do anything in the wrapper.
//extern "C" // this is already C
void common_log(char *msg, int log_prio) {
fancy_logger(msg, log_prio);
}
This requires the linker to be able to resolve undefined symbols in the library using symbols from the program that's linked against it. I think that works, similar to a library providing a weak definition of a global variable, so the main program's definition takes precedence.
If it was ok for simple_logger to also be extern "C" and have the same signature, you could just name them the same and avoid the bounce function. Or if the common function could be an alias for the program's own logging function in either of the programs, I think there are linker tricks to actually do that, instead of compiling to a single jmp instruction (tail-call optimization).
You could implement a callback for getting the program specific output. There's two benefits: no dependency from common part to application (common part defines the interface) and you can make the distinction at run time vs compile time, which gives more legroom for future development, such as changing the output via command line parameters or user interaction.
In the following example, let's refer to the common code part as "library".
library.h
typedef void (*logFunc_t)( logBuffer_t );
void setLogOutput( logFunc_t applicationLog );
library.c
logFunc_t logger; // might be good idea to initialize to an empty function, but omitted here
void setLogOutput( logFunc_t applicationLog )
{
logger = applicationLog;
}
void log( logBuffer_t data )
{
logger( data );
}
application.cpp / application.c
// here you should have the extern "C" in C++ application to ensure linkage compatibility
// I am assuming your shared code is C
extern "C" void myLogger( logBuffer_t data );
int main( int argc, char* agv[] )
{
setLogOutput( &myLogger );
// ...do your thing
return 0;
}
void myLogger( logBuffer_t data )
{
// ...log wherever
}
This question already has answers here:
Closed 13 years ago.
Duplicate of the following question: C function conflict
Hi,
in my current project I have to use some kind of interface lib. The function names are given by this interface, what this functions do is developers choice. As far as I can tell a project shall use this functions and when it comes to compiling you choose the lib and with it the functionality. What I try to do is to use an existing lib and my lib at the same time by wrapping the other and call it in mein functions:
otherlib:
int function1 (int a) {
// do something
}
mylib:
int function1 (int a) {
//my code here
otherlib::function1(a);
}
Problem is I don't have access to the other lib and the other lib doesn't have any namespaces. I already tried
namespace old {
#include "otherlib.h"
}
and then call the old function by old::function1 in my function. This works as long as it's only header file. The lib exports it's symbol back into global space. Also something like
namespace new {
function1 (int a) {
::function1(a);
}
}
didn't work. Last but not least I tried ifdefs and defines suggested here
but I wasn't successful.
Any ideas how to solve this? Thanks in advance.
EDIT: I neither have access to the old lib nor the project both libs shall be used in.
EDIT2: at least the old lib is a static one
Namespaces in C solved using library names prefixes like:
libfoo --> foo_function1
libbar --> bar_function1
These prefixes are actual namespaces. so if you write libbar
int bar_function1(int a) {
function1(a);
}
This is the way to solve problems.
C has namespaces --- they just called prefixes ;)
Another option is to do various dirty tricks with dynamic loading of libraries like:
h1=dlopen("libfoo.so")
foo_function1=dlsym(h1,"function1")
h2=dlopen("libbar.so")
bar_function1=dlsym(h2,"function1")
It seems as if the other lib is C and your code is C++. You can be running into a mangling problem (C++ compilers mangle the symbols -- add extra stuff in the symbol name do differentiate overloads and the like).
If the library is pure C you can try:
extern "C" { // disable mangling of symbol names in the block
#include "otherlib.h"
}
namespace new_lib { // new is a reserved word
int function1( int a ) {
::function1(a);
}
}
I have not tried it. Also consider providing the error messages you are getting.
Another option would be (if the library is dynamic) dynamically loading the lib and calling the function. In linux (I don't know about windows) you can use dlopen to open the library, dlsym to obtain the symbol and call it:
// off the top of my head, not tried:
int function1( int a )
{
int (*f)(int); // define the function pointer
void * handle = dlopen( "library.so" );
f = dlsym( handle, "function1" );
f( a ); // calls function1(a) in the dynamic library
}
In this case, as you are not linking against the library you won't get a symbol conflict, but then again, it is only valid for dynamic libraries and it is quite cumbersome for regular usage.
UPDATE
If your users will not use 'otherlib' directly (they won't include their headers) and they will be only C++, then the first approach could be possible (even if horrible to read):
// newlib.h
namespace hideout {
int f( int a );
}
using namespace hideout; // usually I would not put this on the header
// newlib.cpp
extern "C" { // if otherlib is C, else remove this line
#include "otherlib.h"
}
namespace hideout {
int f( int a ) { return ::f( a*2 ); }
}
// main.cpp
#include "newlib.h"
int main()
{
std::cout << f( 5 ) << std::endl;
}
How does it work? User code will only see a declaration of function1 (in the example f()) as they are not including otherlib.h. Inside your compilation unit you see the two declarations but you differentiate through the use of the namespace. The using statement in the header does not bother you as you are fully qualifying in your cpp. The user main.cpp will include only your header, so the compiler will only see hideout::f, and will see it anywhere due to the using statement. The linker will have no problem as the C++ symbol is mangled identifying the real namespace:
// g++ 4.0 in macosx:
00002dbe T __ZN7hideout9function1Ei // namespace hideout, function1 takes int, returns int
00002db0 T _function1
If user code will include both your header and otherlib.h then it will have to qualify which function it wants to call.
If you're really desperate, you could write a wrapper library that uses namespaces or prefixes or allows for the dlsym trick. This wrapper library would need to be dynamically linked (to avoid symbol conflicts). The dynamic library could then safely have the old static library embedded in it. Just make sure you don't export the symbols from the static library when making the dynamic wrapper library.
You can't resolve this at link time, so you'll need to resolve it at runtime via dynamic libraries. The symbol for those functions is essentially baked it once the library has been generated. If two libraries export the same symbol, they cannot both be linked with statically.