I'm trying to create a C++ dll. I have followed the msdn tutorial but I can't compile my dll correctly.
The problem is that any function is exported. I have tested it with dumpbin.exe tool and nm tool.
In both cases, there is no detected symbols.
Here is the code of this library:
Header file:
#ifndef NLIB_H
#define NLIB_H
#ifdef _WINDLL
#define NLIB_EXPORTS __declspec( dllexport )
#else
#define NLIB_EXPORTS __declspec( dllimport )
#endif
#ifdef __cplusplus
extern "C"{
#endif
NLIB_EXPORTS int fun1(int n);
#ifdef __cplusplus
}
#endif
#endif
Source code file:
#include "nlib.h"
int fun1(int n) {
return 100;
}
I have found the error. It's necessary to add NLIB_EXPORTS to the *.c file also, like this:
#include "nlib.h"
NLIB_EXPORTS int fun1(int n) {
return 100;
}
Related
I am calling Matlab compiled DLLs from C++ code. I use Matab 2015b for development and Matlab 9.0 as runtime.
The following command was used in a Windows 10 64-bit machine to compile Matlab application
mcc -v -a .\+ismrmrd -W cpplib:libStdFourier -T link:lib StdFourier.m -d E:\dev\matlab\mfiles\StdFourier
The DLL call works fine in the development machine. But when I deploy it in another machine which runs on Windows 7 64-bit with Runtime 9.0 installed, the library fails to initialise. The runtime initialises successfully and following error occurs at library intialise method libStdFourierInitialize()
I use following code for initialising runtime and library:
mclmcrInitialize();
const char *rtOptions[3];
rtOptions[0] = "-singleCompThread";
rtOptions[1] = "-logfile";
rtOptions[2] = "matlogfile.txt";
if (!mclInitializeApplication(rtOptions,3))
{
std::cerr << "Could not initialize the application properly." << std::endl;
}
std::cout << "MCR initialized:" << mclIsMCRInitialized() << std::endl; //Returns true
std::cout << "Initialize libStdFourier" << << std::endl;
/* Call the library intialization routine and make sure that the
library was initialized properly. */
if(!libStdFourierInitialize())
{
fprintf(stderr,"Could not initialize the library.\n");
}
And the error console window
Code for the header:
#ifndef __libStdFourier_h
#define __libStdFourier_h 1
#if defined(__cplusplus) && !defined(mclmcrrt_h) && defined(__linux__)
# pragma implementation "mclmcrrt.h"
#endif
#include "mclmcrrt.h"
#include "mclcppclass.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__SUNPRO_CC)
/* Solaris shared libraries use __global, rather than mapfiles
* to define the API exported from a shared library. __global is
* only necessary when building the library -- files including
* this header file to use the library do not need the __global
* declaration; hence the EXPORTING_<library> logic.
*/
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_C_API __global
#else
#define PUBLIC_libStdFourier_C_API /* No import statement needed. */
#endif
#define LIB_libStdFourier_C_API PUBLIC_libStdFourier_C_API
#elif defined(_HPUX_SOURCE)
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_C_API __declspec(dllexport)
#else
#define PUBLIC_libStdFourier_C_API __declspec(dllimport)
#endif
#define LIB_libStdFourier_C_API PUBLIC_libStdFourier_C_API
#else
#define LIB_libStdFourier_C_API
#endif
/* This symbol is defined in shared libraries. Define it here
* (to nothing) in case this isn't a shared library.
*/
#ifndef LIB_libStdFourier_C_API
#define LIB_libStdFourier_C_API /* No special import/export declaration */
#endif
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV libStdFourierInitializeWithHandlers(
mclOutputHandlerFcn error_handler,
mclOutputHandlerFcn print_handler);
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV libStdFourierInitialize(void);
extern LIB_libStdFourier_C_API
void MW_CALL_CONV libStdFourierTerminate(void);
extern LIB_libStdFourier_C_API
void MW_CALL_CONV libStdFourierPrintStackTrace(void);
extern LIB_libStdFourier_C_API
bool MW_CALL_CONV mlxStdFourier(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]);
#ifdef __cplusplus
}
#endif
#ifdef __cplusplus
/* On Windows, use __declspec to control the exported API */
#if defined(_MSC_VER) || defined(__BORLANDC__)
#ifdef EXPORTING_libStdFourier
#define PUBLIC_libStdFourier_CPP_API __declspec(dllexport)
#else
#define PUBLIC_libStdFourier_CPP_API __declspec(dllimport)
#endif
#define LIB_libStdFourier_CPP_API PUBLIC_libStdFourier_CPP_API
#else
#if !defined(LIB_libStdFourier_CPP_API)
#if defined(LIB_libStdFourier_C_API)
#define LIB_libStdFourier_CPP_API LIB_libStdFourier_C_API
#else
#define LIB_libStdFourier_CPP_API /* empty! */
#endif
#endif
#endif
extern LIB_libStdFourier_CPP_API void MW_CALL_CONV StdFourier(int nargout, mwArray& bufferQ, mwArray& imageQ, const mwArray& xmlstr, const mwArray& recon_data);
#endif
#endif
Thanks.
I created a DLL project called Test Lib:
// main.h
#ifndef __MAIN_H__
#define __MAIN_H__
#ifdef BUILD_DLL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
extern "C" {
DLL_EXPORT void print();
}
#endif
// main.cpp
#include "main.h"
#include <iostream>
#define BUILD_DLL
using std::cout;
using std::endl;
extern "C" {
DLL_EXPORT void print() {
cout << "Success" << endl;
return;
}
}
Above code is from following an example I found online that I could understand. When I try to compile and/or build it, I get the following error & warning:
error: function 'void print()' definition is marked dllimport
In function 'void print()':
warning: 'void print()' redeclared without dllimport attribute: previous dllimport ignored
This is the second library I'm ever creating because I'm trying to replicate a problem in the first one, when this happened. What is wrong? I'm using Code::Blocks.
You need to define BUILD_DLL before you include the header file main.h.
#define BUILD_DLL
#include "main.h"
As it stands in your program, you declare print with __declspec(dllimport) because the header file is processed when BUILD_DLL is not defined.
I know there are several questions about this error message but I did not find a suitable solution for my case. I want to export the Filter class from a library. Visual Studio 2013 just compiles fine, but gcc throws the error:
prog.cpp:16:17: error: expected initializer before 'Filter'
class DllExport Filter{
^
prog.cpp:22:6: error: 'Filter' has not been declared
void Filter::setFilter(const std::vector<float>& vFilter, unsigned int uNumThreads) {
^
The code:
#ifndef _GNULINUX
#define DllExport __declspec(dllexport)
#else
#define DllExport __attribute__((visibility("default")))
#endif
#include <string>
#include <vector>
#include <iostream>
#ifdef __cplusplus
extern "C" {
namespace FilterAPI {
#endif
class DllExport Filter{
public:
static void setFilter(const std::vector<float>& vFilter, unsigned int uNumThreads);
};
void Filter::setFilter(const std::vector<float>& vFilter, unsigned int uNumThreads) {
}
#ifdef __cplusplus
} // namespace FilterAPI
} // extern "C" {
#endif
See also
https://ideone.com/3VV4AH
Edit:
flags in the make file are:
# CMAKE generated file: DO NOT EDIT!
# Generated by "Unix Makefiles" Generator, CMake Version 2.8
# compile CXX with /usr/bin/c++
CXX_FLAGS = -fPIC
CXX_DEFINES = -DFilter_Library_EXPORTS
I think that your problem in wrong define,
should be #ifndef __linux, you can find out gcc defaults
with gcc -dM -E - < /dev/null
I don't think you need to explicitly declare the visibility to be "default". It matters on Windows, yes, but on Linux/POSIX the default is what you want.
#ifdef _WIN32
#define DllExport __declspec(dllexport)
#else
#define DllExport
#endif
This is the more common idiom, at least.
I can`t export an array from a DLL. Here is my code:
" DLL header "
#ifdef EXPORT
#define MYLIB __declspec(dllexport)
#else
#define MYLIB
#endif
extern "C" {
/* Allows to use file both with Visual studio and with Qt*/
#ifdef __cplusplus
MYLIB double MySum(double num1, double num2);
extern MYLIB char ImplicitDLLName[];
#else
extern Q_DECL_IMPORT char ImplicitDLLName[];
Q_DECL_IMPORT double MySum(double num1, double num2);
#endif
}
" DLL source"
#define EXPORT
#include "MySUMoperator.h"
double MySum(double num1, double num2)
{
return num1 + num2;
}
char ImplicitDLLName[] = "MySUMOperator";
" client main.cpp"
int main(int argc, char** argv)
{
printf("%s", ImplicitDLLName);
}
When building I am getting from the linker this error:
Error 2 error LNK2001: unresolved external symbol _ImplicitDLLName \Client\main.obj
// My purpose of exporting the array is to study export of different data structs from DLLs
How to cope with the error raised by linker and what rules are violated?
*UPDATE: *
IDE Visual Studio 2010.
Client - is written on C++, also DLL is on C++
Assuming you're linking your import library correctly (and thats a big assumption), you're not declaring MYLIB correctly for importing symbols:
This:
#ifdef EXPORT
#define MYLIB __declspec(dllexport)
#else
#define MYLIB
#endif
Should be this:
#ifdef EXPORT
#define MYLIB __declspec(dllexport)
#else
#define MYLIB __declspec(dllimport)
#endif
Keep in mind we've little context to work with. It looks like you're trying to consume this from a C-compiled application, but without more info I can't be sure. If that is the case, then Q_DECL_IMPORT had better do the above or it still will not work. I'd start with a basic "C" linkage export and work your way up from there.
Sample EXPORTS.DLL
Exports.h
#ifdef EXPORTS_EXPORTS
#define EXPORTS_API __declspec(dllexport)
#else
#define EXPORTS_API __declspec(dllimport)
#endif
extern "C" EXPORTS_API char szExported[];
Exports.cpp
#include "stdafx.h"
#include "Exports.h"
// This is an example of an exported variable
EXPORTS_API char szExported[] = "Exported from our DLL";
Sample EXPORTSCLIENT.EXE
ExportsClient.cpp
#include "stdafx.h"
#include <iostream>
#include "Exports.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
cout << szExported << endl;
return 0;
}
Output
Exported from our DLL
I am writing a (my first) C++ class on top of some code written in C, but I can only get the C++ to compile by declaring the C functions in a extern block. My project uses autotools; is there any way to automate this process so I don't have to maintain two header files?
Use a extern block inside a #ifdef in C codes header files
Start of header files
#ifdef __cplusplus
extern "C" {
#endif
...and at end of the header files
#ifdef __cplusplus
}
#endif
This way it will work for being included in both C and C++ sources
Yes create wrapper header files which include your C header files like so...
//Wrapper.h
#ifdef __cplusplus
extern "C"
{
#include "Actual.h"
}
#else
#include "Actual.h"
#endif
//Use.cpp
#include "Wrapper.h"
int main()
{
return 0;
}
//Use.c
#include "Wrapper.h"
/*or #include "Actual.h" */
int main()
{
return 0;
}
Use the C Preprocessor. Do something like this:
#ifdef __cplusplus
extern "C" {
#endif
// code goes here
#ifdef __cplusplus
}
#endif
We have a macro in a header file:
#ifdef __cplusplus
#define _crtn "C"
#else
#define _crtn
#endif
Then in header files, we can use _crtn:
#include "croutine.h"
extern _crtn void MyFunction( ... );
The only gotcha is to make sure you include the header file containing the prototype of MyFunction inside the file containing the implementation of MyFunction so that it is compiled with "C" linkage.
This is the same as #epatel's answer, but only requires the ugly #ifdef's in one header file.