OSX C++ Export function - c++

I got a large C++ project that uses a makefile on OSX. where I simply want to add an exported function that I can resolve can call. The project needs to be an executeable and not a library. It already exports a bunch of functions but I cannot get my export to work, meaning it's not visible when I run nm on the binary.
I tried to simply add this to the header .h
#define EXPORT __attribute__((visibility("default")))
EXPORT int callme(int test);
I also tried declaring it in the header like
EXPORT int callme(int test) {return 0;}
but then i get a bunch of errors of the symbol already existing in other object files.
Edit: It's a simple C function and I also tried
#if !defined(__cplusplus)
#define MONExternC extern
#else
#define MONExternC extern "C"
#endif
MONExternC int callme (int test);
I'm a bit of novice when it comes to C++ and any insight or help would be much appreciated, thanks.

You have defined (not just declared) a standalone, non-member, non-template, non-inline function in a header. This is exactly the thing you should not be doing. It leads to the sort of errors you describe, and is prohibited by the standard.
You should have only a function ptototype in the header. Move its definition to an exactly one source file.
The visibility attribute only makes sense when building shared libraries. You probably don't need it.

Related

Preprocessor identifier in front of function declarations in a header file

I was reading a header file and I noticed that the programmer has put a preprocessor identifier in front of the return values of functions in their declarations, as following.
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...
namespace SampleName
{
SAMPLE_API bool api_function();
...
}
What's the purpose of it and how does it work?
Edit: I am reading imgui.h from the IMGUI project.
By defining SAMPLE_API (on your compiler command line, in your Makefile / IDE environment etc.), you could add something to each function declaration in this header.
If you did not define SAMPLE_API, the first couple of lines...
#ifndef SAMPLE_API
#define SAMPLE_API
#endif
...make sure that SAMPLE_API is "defined away", i.e.
SAMPLE_API bool api_function();
...is preprocessed to...
bool api_function();
...so "nothing happens" (instead of "syntax error" when the compiler runs into SAMPLE_API and does not know what to do with it).
The usual reason for a construct like this SAMPLE_API symbol is to handle symbol export / import when building / using a library for Windows.
You would define SAMPLE_API to...
__declspec(dllexport) when building a library for Windows,
__declspec(dllimport) when using a library for Windows,
...so the symbols for the functions in question get exported / imported as necessary.
There are other things that could be done with such a preprocessor symbol (like deprecating functions, so that the linker will warn if they are being used), or other platform-specific stuff. But I would guess you're looking at dllexport / dllimport plumbing here.
In this particular case it does nothing. (Remember that the preprocessor does little more than trivial copying and pasting).
But, it might be useful in some instances to declare for example, a declspec for exporting a DLL function (in which case it would be #DEFINEd to something less trivial. Needless to say, that kind of thing is not formally part of the C++ standard, but rather is likely exploiting compiler extensions.

Default linkage model in gcc 4.4 vs. gcc >4.4

I'm trying to use two large, complex linear algebra libraries which define many of the same functions. I can't rewrite (legally in one case, but technically in both) either of them. Let's call them "special" and "normal" because I only call a couple functions from special. To consistently call functions defined in normal.h and only in some cases from special.h, I've done something like this:
namespace special_space
{
#include "special.h" // Defines foo()
}
#include "normal.h" // Defines foo()
int main() {
foo(); // Calls foo() defined in normal.h
special_space::foo(); // Calls foo() defined in special.h
}
With g++-4.4, which was the default where I was developing this, the code compiles and links without warnings, and it executes as I would expect and as I want. This seems to be consistent across platforms, various Linux, Unix and BSD environments. But! if I compile with g++ >4.4, I get warnings about multiple foo() definitions:
In file special.h::line:col: warning: declaration of ‘void
special_space::foo()’ with C language linkage [enabled by default]
The resulting executable then segfaults at the call to special_space::foo(). I /think/ that specifying extern "C++" in the definitions found in special.h might fix this, but I'm not allowed to change special.h. So what should I do? More specifically:
1) Is it safe to use g++-4.4? If so -- what changed in subsequent versions and why?
2) If specifying the C++ linkage model really would fix this, is there a way to tell ld to use it by default?
3) If neither of those -- is there another way to call functions from libraries that define functions of the same name?
So as I posted in a comment, wrap the headers includes with
#ifdef __cplusplus
extern "C" {
#endif
#include normal.h
#ifdef __cplusplus
}
#endif
Do this with both headers.
Basically, since you're linking c libraries from c++, which does name mangling (this is what allowes overloading), your calls to the symbols in your c lib were being mangled by the linker. The #ifdef __cplusplus tells the linker not to mangle the names for those specific function symbols.
Ideally, the creators of the library should include this in their headers but you mentioned that you have no control over that. I had a similar problem with some generated code. I had to wrap all my header includes of the generated code in this to allow C++ to call it.
What I don't know, is how it ever worked without this. I've definitely had to do this going back to gcc < 4.4.

How do I fix an Unresolved External Symbol error in my C++ DLL?

I have a dll, which accesses some classes outside of its project (I'm using Visual Studio, so I have two projects). The thing is, in the header that the dll includes, which is outside of the dll's project, there are only bodies of functions, like this:
x.h
class x
{
void myFunc();
}
And in another cpp file, outside of the dll file:
#include "x.h"
x::myFunc()
{
//.....
}
The dll is only getting the bodies of the functions, so when I compile, I get lots of unresolved external symbols (I'm quite sure that this is the issue, because I tested with another class fully built in a .h file, in another project, and no errors). So how can I solve this mystery?
It is normal for the import headers to only have function signatures; the actual function bodies are already compiled into the DLL binary and are resolved at link time by linking into the actual DLL.
The first thing to try is to make sure you are actually linking to the said DLL. It isn't enough to just include the header, you also need to link to the binary. So in your project configuration, you need to add a link to (for example) the .lib file that gets created along-side the DLL when the DLL is compiled (if in MSVC). This lib file lets the linker know how to connect the function signatures you included via the import header to the actual implementations contained in the DLL. If you're on a different platform, the mechanics might be a little different, but the concepts will be similar.
Edits:
The next step is to make sure the binary is actually exporting the symbols you're trying to link against. Make sure that all interface signatures are being exported via __declspec(dll_export) prefixes. Normally this is wrapped up in an IFDEF so that the header is declared export while the DLL is being compiled, but not when that header is included in a client project. Next, you could use dumpbin to check the mangled export names, and see if there is anything unexpected.
Here's a modified version of your example that illustrates this style of export (note, I haven't tested if this compiles, apologies for any typos):
#ifdef BUILDING_MYDLL
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class MYDLL_API x
{
void myFunc();
}
You would then set your configuration to define BUILDING_MYDLL when compiling the dll, but not when compiling the executable. This way the functions are only marked export when compiling the library dll. Now you can mark your public API functions with MYDLL_API and they should get exported during build.
Please note that dll_export, dll_import, and declspec are all very MSVC-specific constructs. Other compilers/runtimes handle symbol export in different ways.
There's multiple ways to link DLL into your app on Windows, check out this existing question/answer:
https://stackoverflow.com/a/2060508/1701823

Linking to a C library compiled as C++

I'm in linker paradise now. I have a C library which only compiles in Visual C++ (it probably works in gcc) if:
I compile it as C++ code
Define __cplusplus which results in all the declarations being enclosed in extern "C" { }
So, by doing this I have a static library called, say, bsbs.lib
Now, I have a C++ project called Tester which would like to call function barbar in declared in bsbs.h. All goes fine, until I try to link to bsbs.lib where I get the all-too-familiar:
Tester.obj : error LNK2001: unresolved external symbol _foofoo
And it always seems to be foofoo which cannot be resolved regardless of which function I call in Tester (barbar or anything else).
Update: I've expanded on Point 2 as requested. Thanks a lot for the help guys!
#ifndef _BSBS_H
#define _BSBS_H
/* Prevent C++ programs from name mangling these definitions. */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <setjmp.h>
.......
.......
#ifdef __cplusplus
}
#endif
#endif /* _BSBS_H */
This is the "main" header file, so to speak. All the important functions are here. But there are other header files called by the bsbs.c file which are not enclosed in extern "C" {}.
Solved:
OK, this is quite weird, but I removed the extern C bit from the header file in bsbs, compiled it as a C++ project (even though all the files are .c and removed the __cplusplus define) and it worked! I got the idea after looking at the symbol list. Everything was mangled except the ones enclosed in extern C (doh) and it was asking for an unmangled symbol so I figured something was amiss.
If you declare them as extern C in the lib (which is unnecessary, if you're calling them from C++), then they must be extern C in your headers.
There may be a dependency in the c library you're not including in your link. Does the c library you're including really a reference to a DLL? If so there's a program called 'depends' which will tell you what the other required DLL's are.
I'm assuming you've added a linker reference. E.g.:
#pragma comment(lib, "bsbs.lib")
Perhaps the compiler/linker combination needs to be made aware of which APIs are to be exported/imported? If so I'd try adding the appropriate __declspec (e.g., dllimport and/or dllexport) to the C++ library.
Does your lib file import any other lib files? You can compile a lib file to either explicity link lib files or implicitly. One way you get the lib files in a huge ball, the other you get them as separate libs that all need linked at compile time in the final app. If foofoo is imported in your lib file from another lib file, then include that lib file in your final project. This is my best guess from what you described, and is by far the most common thing I get asked when dealing with lib files thru co-workers..

DLL : export as a C/C++ function?

I generated a DLL in Visual from a C++ code. Dependency Walker sees 3 functions exported as C functions.
I made an SCons project to do the generate the DLL, and 2 of the 3 functions are not seen as C functions.
What makes a function seen as a or C++ function, without modifying the code ? It must be in the compilation/linking options, but I didn't find any relevant thing.
The function are prefixed by a macro : AM_LIB_EXPORT
In the .h, I have :
#ifdef _WIN32
#define AM_LIB_EXPORT __declspec(dllexport)
#else
#define AM_LIB_EXPORT
#endif // _WIN32
Thanks.
What makes a function seen as a or C++ function, without modifying the code ?
A function compiled by a C++ compiler is automatically a 'C++-function' and name-mangling occurs to resolve C++ features such as namespaces and overloading.
In order to get 'C' export names, one must use the aforementioned extern "C" qualifier in the function declaration. Alternatively a huge extern "C" { .. } block around the header containing the prototypes.
If this does not solve your issue, its maybe related to dllimport/dllexport. If you #define AM_LIB_EXPORT __declspec(dllexport) in your DLL build, you'll typically also need to make it dllimport for apps linking against your DLL in order for the linker to know where to fetch the symbols from.
Is this a name mangling issue? If you don't use extern "C" around your function declarations, they will get name-mangled.
I found the reason :
The export was also added as additionnal command line option (/EXPORT). In this case, it is exported as a C function. I don't understand why...
I removed this additionnal command line switch.
Thank you all.
I still don't know how to mark a thread as "resolved" ?