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

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" ?

Related

Py ILM Base not compiling on windows

I've downloaded the latest copy from Latest Open EXR repo and compiled most everything without any problems. However, when I get to PyILMBase it fails.
There are two distinct issues with my attempts:
Error C2491 'PyImath::FixedArray::name': definition of dllimport function not allowed PyImath (...)\src\pyilmbase-2.2.1\PyImath\PyImath.cpp 41
and an import to unistd.h that kind of gets addressed Here
my question being, has anybody successfully compiled this for windows? It seems odd that I can't find any specific info about that compiling error. Am I missing something in the way that C++ works?
This project makes extensive use of whatever it is that causes the error C2491, so going in and changing it would be a little complicated
IlmBase is compiled as a shared library. A shared library must provide their function declarations in order your program can find them.
It's perform by declaring them as dllimport or dllexport depending on the situation.
__declspec(dllimport): imports the implementation from a DLL so your application can use it.
__declspec(dllexport): tells the linker that you want this object to be made available for other DLL's to import. It is used when creating a DLL that others can link to.
These keywords are generally handled by a single macro. In your case PYIMATH_EXPORT.
These lines are from PyImathTask.h
#if defined(PYIMATH_EXPORTS) // create library
#define PYIMATH_EXPORT __declspec(dllexport)
#else // use library
#define PYIMATH_EXPORT __declspec(dllimport)
#endif
So, because you want to make these functions available from your application, you must add PYIMATH_EXPORTS as a preprocessor definition.
Actually, PyIMath's properties mispells it - they've write it as PyImath_EXPORTS - ...
To fix that, in vs2015, go to the PyImath's properties > Configuration Properties > C/C++ > Preprocessor > Replace PyImath_EXPORTS by PYIMATH_EXPORTS.
It's probably the same thing for PyIex...

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.

OSX C++ Export function

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.

What is dllspec(dllimport) and dllspec(dllexport) means

After googling, i came to know that Dllimport makes the function available for other modules,
is it mandatory to declare function with extern "c" identifier?
Also, Dllexport means, Dll itself uses the function while compiling it says. so by default all
functions present in DLL are dllexport?
__declspec(dllexport) exports a symbol. It makes it available from outside a DLL.
__declspec(dllimport) imports a symbol. It practically says "this symbol is not defined in this application, it needs to be imported from a DLL file".
You don't have to declare it with extern "C". If you don't use extern "C", then the symbol will be exported as a C++ symbol, and you will only be able to call it from C++ (and languages that support calling C++ DLLs). If you use extern "C", then the symbol will be exported as a C symbol, and you will be able to call it from languages that support caling C DLLs.
If you want to use your DLL in C#, you will need to use extern "C".
Here is an excellent tutorial that shows you how to use a C++ DLL in C#: How to marshal a C++ class. I have used solution A in many projects at work.
Also, here is a short tutorial on how you can use a C++ DLL in another C++ application: How to create and use DLL in C++.
No -- dllexport means you're exporting it from the DLL (or from an executable) so that other modules (DLLs or executables) can use that function.
dllimport is used to declare a function that's implemented in a DLL (or, again, executable).
So, in a typical case, you'll have something like:
#ifdef BUILDDLL
#define DLL declspec(dllexport)
#else
#define DLL declspec(dllimport)
#endif
Then each public function the DLL will be marked as DLL:
DLL int dosomething(int);
Then, when you're building the DLL, you'll define BUILDDLL, to have all those functions marked as dllexport. Otherwise, you'll include the same header in client code that needs to use the function(s). It won't define BUILDDLL, so they'll all be marked as dllimport instead, so when it comes to link time, it'll create a link to that DLL instead of trying to satisfy those functions from someplace like the standard library.
It also means that entries (in the form of static import and export tables) are created (by the linker) in the exe, dll..files, which document the dependencies between a provider and a consumer.

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..