I was following a tutorial on how to create a C++/Cli DLL, for some reason I get a warning for each function declaration, here's the whole code:
// KRecognizer.h
#pragma once
namespace KR
{
class __declspec(dllimport) KinectRecognizer
{
public:
KinectRecognizer();
~KinectRecognizer();
int Display();
};
}
_
// KRecognizer.cpp
#include "stdafx.h"
#include "KRecognizer.h"
using namespace System;
KR::KinectRecognizer::KinectRecognizer()
{
}
KR::KinectRecognizer::~KinectRecognizer()
{
}
int
KR::KinectRecognizer::Display()
{
Console::WriteLine(L"Writing a line");
return 100;
}
Here are the error outputs:
http://pastie.org/3678144
I'm compiling with the /clr flag.
The header declares DLL import, which means the definition of the class comes from a DLL. Since you are providing the definition, this gives the linkage error. You'll want to use __declspec(dllexport) instead when defining the DLL.
Since you'll want to use the same header file in the app that will use the DLL, the following idiom is often used:
#ifdef MYAPI_EXPORTS
# define MYAPI __declspec(dllexport)
#else
# define MYAPI __declspec(dllimport)
#endif
And then use:
class MYAPI KinectRecognizer
#define MYAPI_EXPORTS before including the header in the DLL, but do not define it in the application using the header to import the DLL.
Related
In visual studio I've set configuration type as .dll instead of .exe and because of that sometimes I need to use __declspec(dllexport) or __declspec(dllimport) . So I've created macros for them inside header file called "Core"
#pragma once
#ifdef B5_PLATFORM_WINDOWS
#ifdef B5_BUILD_DLL
#define B5_API __declspec(dllexport)
#else
#define B5_API __declspec(dllimport)
#endif // B5_BUILD_DLL
#else
#error Bos5 only supports Windows!
#endif // B5_PLATFORM_WINDOWS
I have a class "Application" inside of my namespace "Bos5" which uses BS_API
#pragma once
#include "Core.h"
namespace Bos5 {
class B5_API Application
{
public:
Application();
~Application();
void Run();
};
}
everything works fine inside this project but when I reference this to another project for some reason visual studio thinks B5_API is a class and "Application" isn't. therefore code below doesn't compile saying namespace Bos5 doesn't have struct or class called "Application"
#include <FinalBos5.h>
class Sandbox : public Bos5::Application
{
public:
Sandbox(){}
~Sandbox(){}
};
int main() {
}
I think this image can better explain what I'm saying
Okay I've fixed it. turns out problem was completely different thing. My preprocessor didn't save some of the definitions so in second project B5_API wasn't getting defined
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);
It would appear that the example couldn't get any simpler:
//Example.h
#pragma once
#ifdef EXPORTING_DLL
extern __declspec(dllexport) void HelloWorld();
#else
extern __declspec(dllimport) void HelloWorld();
#endif
//Example.cpp
#include "Functions.h"
#define EXPORTING_DLL
void HelloWorld()
{
}
So, what I have problems with? OK, when trying to compile as it is, that is after creation of dll type project in VS, I'm getting warning:
warning C4273: 'HelloWorld': inconsistent dll linkage
if I change definition of HelloWorld in cpp file to:
__declspec(dllimport) void HelloWorld()
{
}
I'm getting error:
Error C2491 'HelloWorld': definition of dllimport function not allowed
If on the other hand I change definition of HelloWorld to:
__declspec(dllexport) void HelloWorld()
{
}
I'm getting warning:
Warning C4273 'HelloWorld': inconsistent dll linkage
Any idea how to define it so it compiles without any warnings? I mean, those warnings are at least worrying.
You need to define EXPORTING_DLL before you include the header. That way the header can declare the correct prototype based on whether you are importing or exporting.
Without doing this it will import which is not what you want
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"
On the .dll file
//SWC.h
#ifndef _SWC_
# define _SWC_
# define SWC_CALL __declspec(dllexport)
#else
# define SWC_CALL __declspec(dllimport)
#endif
namespace SWC
{
struct SWC_CALL Mouse
{
//interface
};
class SWC_CALL SWC_Base : public someClass1, public someClass2
{
static Mouse mouse;
};
//other classes goes here...
}
//SWC_Base.cpp
namespace SWC
{
Mouse SWC_Base::mouse; //needed, to compile
//other SWC_Base function definition
}
On .exe file
with the static struct Mouse mouse I defined on the SWC_Base I get linking errors
I solve my problem by redefining it again on this file
//main.cpp
#include "SWC.h"
#pragma comment (lib, "..\\SWC")
SWC::Mouse SWC::SWC_Base::mouse; //<- why do I need to redefine it again?
int main()
{
//...
return 0;
}
I already define the SWC_Base::mouse on its .cpp file, why do I need to redefine it again on the file who uses it? I know I can have this more problems as my .dll project is growing with static variables on it.
If your calling code will use __declspec (dllimport) this trouble will be gone :)
#ifdef EXPORTING_SWC
#define SWC_CALL __declspec(dllexport)
#else
#define SWC_CALL __declspec(dllimport)
#endif
You have added an anymous namespace { } around your definition (in case that you posted the real code) in the header file. Each anonymous namespace will translated to a compilation unit specific namespace by the compiler. Therefore you get always a new class in a new namespace.
To solve the problem you can either
move the declaration, the defination, and all use to one source file
use a named namespace