C++ Visual Studio Windows: how to declare but not define extern function in dll - c++

I have a project that is compiled into a library and declares a certain function to be implemented by the user of the library:
//To be defined by user
Application* CreateApplication();
When compiling the code into a shared library on Linux this works perfectly. Any user of the library can define an implementation for the declared function and it can be used inside the library. If the user of the library forgets to define an implementation, they will get an error pointing this out.
I'm now in the process of porting the library to Windows, where it is supposed to be compiled into a dll. However, I'm running into problems as the linker used by Visual Studio is complaining:
unresolved external symbol Application* __cdecl CreateApplication(void)
I tried adding the extern keyword to indicate that the definition of the function is somewhere else, but this didn't work.
Why can't I declare (but not define) a function in a dll like this? How should I fix my code so it works both on Linux and on Windows?

What you are attempting to do only works in a static library, it cannot work in a dynamic library like a DLL. For that, you will have to change the code to use a function pointer instead. The application that is using the DLL can pass in the address of the desired function from its own code, and the DLL can then assign that address to a variable that it uses as needed, eg:
HEADER:
#ifndef MYLIB_H
#ifndef MYLIB_H
#ifdef COMPILING_MY_LIB
#define MY_EXPORT __declspec(dllexport)
#else
#define MY_EXPORT __declspec(dllimport)
#endif
// declare Application as needed...
typedef Application (*lpCreateApplicationFunc)();
#ifdef __cplusplus
extern "C" {
#endif
MY_EXPORT void SetCreateApplicationFunc(lpCreateApplicationFunc func);
#ifdef __cplusplus
}
#endif
#endif
DLL:
#define COMPILING_MY_LIB
#include "MyLib.h"
//To be defined by user
lpCreateApplicationFunc CreateApplication = NULL;
void SetCreateApplicationFunc(lpCreateApplicationFunc func)
{
CreateApplication = func;
}
void doSomething()
{
Application *app = NULL;
if (CreateApplication)
app = (*CreateApplication)();
if (app)
{
...
}
}
EXE:
#include "MyLib.h"
Application MyCreateApplicationFunc()
{
...
}
// during startup, call this...
SetCreateApplicationFunc(&MyCreateApplicationFunc);

Related

Exporting extern variables from dll visual C++

Basically I have a dll project in visual studio. I'm linking this dll project to a second project successfully but as soon as I try to use extern variables things go wrong. I've seperated my extern variables into a single header and source file from everything else so I can isolate the problem and potential solutions. I've scowered the internet for hours now and I feel like I've tried everything. I am beginning to think it might be a compile flag? Anyway, heres my code.
macros.h
#pragma once
// dll management
#ifdef TOAST_EXPORT
#ifdef _MSC_VER
#define TAPI __declspec(dllexport)
#else
#define TAPI __attribute__((visibility("default")))
#endif
#else
#ifdef _MSC_VER
#define TAPI __declspec(dllimport)
#else
#define TAPI
#endif
#endif
globals.h
#pragma once
#define TOAST_EXPORT
#include "macros.h"
namespace toast
{
TAPI extern const char c;
}
globals.c
Note that I tried this without const and made no assignment here
#pragma once
#include "globals.h"
namespace toast
{
const char c = 'a';
}
main.c (from the project that compiles to an exe)
#include <globals.h>
int main()
{
char c = toast::c;
return 0;
}
So far I've tried making a lot of subtle changes like reordering extern and const and such. I've also done it both with just extern and just const. Still produces the same unresolved external symbol "char const toast::c" error. Keep in mind that I can create instances of classes and call their methods from the dll successfully and thats with things like class TAPI logger... and such.

How to call outside function from DLL?

I'm creating a DLL.
my DLL is calling a function passDTMFToClient(int id,DTMF_01 packet) where DTMF_01 is a structure;
and that function definition is present in the other file, outside of DLL where I'm going to reference this dll.
I do not want to move that function to my dll. Thus how can I call it from dll?
For e.g.
DLL :
void DTMF()
{
passDTMFToclient(int id,DTMF_01 packet);
}
Another Project's file Where the definition is available and where the dll will be referenced.
Demo.cpp :
void passDTMFToClient(int id,DTMF_01 packet)
{
.
.
}
DLL.h
#pragma once
#ifdef _WIN32
# ifdef BUILDING_MY_LIB
# define MY_EXPORT __declspec(dllexport)
# else
# define MY_EXPORT __declspec(dllimport)
# endif
#else
# define MY_EXPORT __attribute__ ((visibility ("default")))
#endif
// declare as dll method
MY_EXPORT void passDTMFToClient(int id, DTMF_01 packet);
Ensure that header is included by both you dll.cpp and exe.cpp. Ensure in your dll build you define 'BUILDING_MY_LIB' when compiling on windows. When compiling the dll you should also get a link library (e.g. you'll have mydll.dll and mydll.lib on windows).
Your exe now just need to include the dll.h, and link to the mydll.lib (or mydll.so on linux). If your app can find the dll, it will automatically be loaded.
If you wish to go one step further and load the dll on the fly into your exe, you'll probably want to change the function prototype to:
MY_EXPORT extern "C" void passDTMFToClient(int id, DTMF_01 packet);
Which will disable name mangling. You should be able to open the DLL using LoadLibrary on windows, or dlopen on linux. e.g.
// on windows
HMODULE dllHandle = LoadLibrary("mydll.dll");
// on linux
void* dllHandle = dlopen("mydll.dll", RTLD_NOW);
You will need a function pointer, e.g.
// typedef func type
typedef void (*passDTMFToClient_func)(int, DTMF_01);
// the function pointer
passDTMFToClient_func passDTMFToClient = 0;
You should then just need to get the symbol address, which you do like so on windows:
passDTMFToClient = (passDTMFToClient_func)GetProcAddress(dllHandle, "passDTMFToClient");
And like so on linux:
passDTMFToClient = (passDTMFToClient_func)dlsym(dllHandle, "passDTMFToClient");
And when you're done with the DLL, you can close it again:
// windows
FreeModule(dllHandle);
// linux
dlclose(dllHandle);

How to properly create a DLL from C code and use it in a C++ project

I have a set of functions written in C that I need to be able to call from another project written in C++. The C code is essentially some functions that do some calculations on a large data set. I didn't write them - all I want to do is allow my C++ project to be able to call those functions. My solution was to create a DLL for the C code and link it to my C++ project.
In order to make the DLL, I structured myCproj.h (the header in the C project, not C++ project) like so:
#ifdef __cplusplus
extern "C" {
#endif
struct __declspec(dllexport) neededStruct {
int a;
//I need to be able to initialize this struct in my C++ project.
}
__declspec(dllexport) void neededFunc( struct neededStruct *input ) {}
//I need to be able to call this function from my C++ project and feed
//it my local instance of neededStruct.
#ifdef __cplusplus
}
#endif
The src file, myCproj.c, was not changed at all. The function definitions do not have __declspec(dllexport)in front of them, nor is extern "C" inserted anywhere. The code compiles without error and produces myCproj.dll and myCproj.lib.
I then tell my C++ project in VS where to find myCproj.lib and myCproj.h accordingly and copy the DLL over to the directory where my C++ executable lives. To use the DLL, I gave myCPPproj.cpp the following addition:
#define DLLImport __declspec(dllimport)
struct DLLImport neededStruct input;
input.a = 0;
extern "C" DLLImport void neededFunc( &input );
However, I get error EO335 'linkage specification is not allowed' on that last line. What am I doing wrong?
It is preferable to use the same header for both the library and using code.
As mentioned, it is usually done by a conditional define, like the following:
MyLibrary.h:
#if defined(MYLIBRARY_API)
#define MYLIBRARY_EXPORTS __declspec(dllexport)
#else
#define MYLIBRARY_EXPORTS __declspec(dllimport)
#endif
#if defined(__cplusplus)
extern "C" {
#endif
MYLIBRARY_API bool MyLibFunc();
#if defined(__cplusplus)
#endif
MyLibrary.c:
#include "MyLibrary.h"
void MyLibFunc()
{
....
}
App.cpp:
#include <MyLibrary.h>
int main()
{
MyLibFunc();
}
The symbol MYLIBRARY_API will be defined for the library project (usually as a /D on the compiler command line). And if you use visual studio that is pretty much exactly what you get when creating a dll project with exports.

dynamic library don't generate lib file using visual studio 2012

I am using Visual Studio 2012 and I creared dll without using MFC, it generating the dll. But when I specify to generate a lib file in specific directory using the following option:-
go to proeperties page->Advanced->Import Library
../../../lib/myapp.lib
It is not genearting the lib file in the specified folder. Please help me .
Thanks & Regards
Vikas
Just resolved a similar problem. Visual Studio does not create a .lib file without instructing which objects to expose in dll. You need to create a win exports header like this:
#ifndef BLABLABLA
#define BLABLABLA
#ifdef MYAPPLIB_EXPORTS
#define MYAPPLIB_API __declspec(dllexport)
#elif defined(MYAPPLIB_EXPORTS_STATIC)
#define MYAPPLIB_API
#else
#define MYAPPLIB_API __declspec(dllimport)
#endif
#endif // !BLABLABLA
Then, you need to declare MYAPPLIB_EXPORTS as a preprocessor macro. After including this new header file in other API headers, for every class or method which you want to expose in your API, you can add MYAPPLIB_API to their declarations like:
class MYAPPLIB_API MyClass{ ... };
calculatelibrary.h
/*
By default, the New Project template for a DLL adds PROJECTNAME_EXPORTS to the defined preprocessor symbols for the DLL project.
In this example, CALCULATELIBRARY_EXPORTS is defined when your calculateLibrary DLL project is built.
When the CALCULATELIBRARY_EXPORTS symbol is defined, the CALCULATELIBRARY_API symbol sets the __declspec(dllexport) modifier on the member function declarations in this code.
This modifier tells the compiler and linker to export the function or variable from the DLL so that it can be used by other applications.
When CALCULATELIBRARY_EXPORTS is undefined—for example, when the header file is included by a client application—CALCULATELIBRARY_API defines the __declspec(dllimport) modifier on the member function declarations. This modifier optimizes the import of the function in an application. For more information
*/
#ifndef _calculate_library_h
#define _calculate_library_h
#ifdef CALCULATELIBRARY_EXPORTS
#define CALCULATELIBRARY_API _declspec(dllexport)
#else
#define CALCULATELIBRARY_API _declspec(dllimport)
#endif
namespace calculatelibrary
{
class CALCULATELIBRARY_API clsCalculateLibrary{
// Returns a + b
double Add(double a, double b);
};
}
#endif _calculate_library_h
// CalculateLibrary.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "CalculateLibrary.h"
namespace calculatelibrary
{
double clsCalculateLibrary::Add(double a, double b)
{
return a + b;
}
}
See the following: you may need to declare /EXPORTS (http://msdn.microsoft.com/en-us/library/7k30y2k5.aspx)
http://msdn.microsoft.com/en-us/library/67wc07b9.aspx see "REMARKS"

Linker error trying to call extern "C" function from dll

I'm trying to use a C++ class from a native .dll project in a C++/CLI .dll project. Visual Studio 2010, .NET Framework 3.5. So far this is what I have:
// This is a common macro:
#ifdef ISDLL
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif
NativeProject:
//INativeType.h:
class DLL INativeType {
public:
virtual void Foo() = 0;
};
//NativeType.h:
class DLL NativeType : public INativeType {
public:
virtual void Foo();
};
extern "C" DLL INativeType CreateNativeType();
//NativeType.cpp:
void NativeType::Foo() {}
extern "C" DLL INativeType* CreateNativeType() {
return new NativeType();
}
C++/CLI Project:
// Wrapper.h:
#include "INativeType.h"
ref class Wrapper {
INativeType* m_nativeType;
};
// Wrapper.cpp:
#include "Wrapper.h"
#include "NativeType.h"
// in some method:
m_nativeType = CreateNativeType();
This gives me the following linker error:
error LNK2028: unresolved token (...) "extern "C" class INativeType * __stdcall CreateNativeType(void)"" ... in Wrapper.obj
Also, although the functions are correctly exported in NativeProject.dll, as I verified it with DependencyWalker, the linker also gives this warning:
warning LNK4199: /DELAYLOAD:NativeProject.dll ignored; no imports found from NativeProject.dll
The C++/CLI project is configured to delay load NativeProject.dll and also includes NativeProject.lib in its linker options. At this point I don't know how to diagnose this linker error. What am I doing wrong?
Why don't you just let the C++/CLI project instantiate the class directly instead of with a factory method?
Besides that, it just looks like you are re-inventing COM (using objects through interfaces). I would just instantiate full-blown C++ classes or, if you really need it, use full-blown COM.
EDIT: Make sure the factory method's calling convention is the same in both the client and the DLL.