I have one Visual Studio solution which consists of two win32 projects: 1) application (.exe) 2) functions wrapper (.dll).
The solution is in prototyping stage so all classes/functionality are implemented under (.exe) project - dirty but quick and easy for debugging/testing.
I've started to write a DLL wrapper to "play" with functionality in MSExcel/VBA and faced linking error
error LNK2019: unresolved external symbol "public: __thiscall Date::Date(int,int,int)" (??0Date##QAE#HHH#Z) referenced in function addNumbers
DLL header file:
#ifdef LIBRARYWRAP_EXPORTS
#define LIBRARYWRAP_API __declspec(dllexport)
#else
#define LIBRARYWRAP_API __declspec(dllimport)
#endif
LIBRARYWRAP_API int _stdcall addNumbers(int a, int b);
DLL source file:
#include "..\applicationProject\Date.h"
class Date;
LIBRARYWRAP_API int _stdcall addNumbers(int a, int b){
Date dummyDate(12,1,2014); // <- Linker error LNK2019.
return (a+b);
}
Class Date and constructor Date::Date(int,int,int) are defined in application project(.exe) within Date.h, Date.cpp.
What I've tried to do already:
for librarywrap project added new reference. Project -> Properties -> Common -> Add New Reference. Selected "applicationProject".
added additional include directories: $(SolutionDir)\applicationProject
Two questions:
First, Is that legal/achievable what I'm trying to do? DLL links to application project, whereas usually it should be other way round - application links to DLL. Hypothetically if i have two application projects (.exe) & (.exe) will it be possible to link one to another?
Second, If answer for first question is positive what should I add/change to make it work?
Thanks very much!
Nicholas
Technically, it is possible to make a DLL to call all needed functions from another modules (even from .exe ones - LoadLibrary can do this), but it would be a great pain: you will have to export all needed methods explicitly in the .EXE (just like you export DLL functions) and import them into your DLL. So the answer to the first question is yes, but if the DLL wants to use a lot of entry points from the EXE then probably it is not the best option.
I'd suggest a different approach: having a common code base for both .exe (application) and .dll projects. Then you will be able to test your code by running the application, and to use the functionality from other apps through the DLL (the DLL will contain all the necessary code itself).
Related
Development environmnet: Windows 10, Visual Studio 2017.
I have the following methods defined in api.h and implemented in api.cpp then compiled into api.dll. Compilation also produced api.lib.
extern "C" int validate( int v_mode, char * data, int data_length );
I have created another different project. In that project I included api.h, and then from project settings, I added api.lib into additional libraries to link with as well as I set the additional libraries directory.
This project is super simple console application with which I will test the previously mentioned validate method.
#include "api.h"
int main() {
char data[] ={1,2,3};
validate(ValidationModes::Video,data,3);
}
I get the following error:
error LNK2019: unresolved external symbol validate referenced in function main
Well as the compiler is telling it is linking error. After a bit of searching, I added __declspec(dllexport) to my validate method.
extern "C" __declspec(dllexport) int validate( int v_mode, char * data, int data_length );
Then I could compile and run without any problems. My question is the following:
For any method, class, variable etc, which exists in A.dll, if I try to access those methods, classes, variables etc. from an outside source such as my test application, do I have to set them as __declspec?
I am fairly new to c++ development in Windows environment. I do not remember ever doing something similar to this when I was using g++. Thanks in advance.
Yes, if you wanna use those "names" (function, variable, class, etc.) outside the DLL, you have to "export" them. Note that you only need to do that on Windows (where symbols are not exported from DLL by default). On Linux it's the opposite - all symbols are exported and you'd need to hide whatever you don't want to be exported.
I have a library of DSP functions in C++ and I want to link to them dynamically at run time. I am using the PDLL.h method to wrap my classes (for example FFT) into C-style functions and load them load on the fly in other C++ applications. I want to use these functions in .NET applications and COM components, so I have to use __stdcall which decorates the names in 32 bit builds.
In order to undecorate the names, I am using the trick mentioned here: C++ DLL Export: Decorated/Mangled names (wqw's answer, 2nd down). So for example, in my library's .h file I have declared my wrapped functions so:
#pragma comment(linker, "/EXPORT:DoFFT=_DoFFT#12")
RTLIBS_API DoFFT(FFT* x, DOUBLE* pdDataIn, DOUBLE* pdDataOut);
This does indeed work, and when I look into the dll with dependency walker, I see that there is both an entry for DoFFT and _DoFFT#12.
The problem that I have is that when I try to build a project that links to this library (dynamically, at run time, not using the .lib file at all) I get linker errors for all the functions in my dll, i.e.:
Error 31 error LNK2001: unresolved external symbol _DoFFT#12
I don't understand why this is happening. First of all, the symbol _DoFFT#12 does exist (according to dependency walker) and second of all, why is the linker looking for it in the first place? I am linking to it at run time, not at compile time so how does my project even know about this symbol?
All the functions are declared with the same chain of macros that reduces to (e.g.):
extern "C" __declspec(dllexport) int __stdcall DoFFT(FFT* x){...}
Nothing having to do with the library is declared on the client side.
I want to create a dll that exports a function and a struct. I went through the walkthrough and here is what I have:
Project myDll: the_dll.h
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
typedef struct MyStruct
{
bool b;
} MYSTRUCTTYPE, *PMYSTRUCTTYPE;
typedef const MYSTRUCTTYPE *MYCSTRUCTTYPE;
MYDLL_API bool dllF();
Project myDll: the_dll.cpp
#include the_dll.h
bool dllF() { return true };
In the Preprocessor definitions of the myDll project, I define MYDLL_EXPORTS
In Linker -> Advanced -> Import Library I see $(OutDir)$(TargetName).lib
Yet there is no lib generated, only dll and pdb
Intellisense shows MYDLL_EXPORTS to be __declspec(dllexport) and the dllimport portion is grayed out... So I must be exporting...
I have included the dependent header file, and set the additional library directories and additional include directories, as well as dependent libs, in the caller project. But... in the absence of the lib...
The project that requires the functions from this dll gives unresolved external symbol error.
How can I make my dll create a lib ? What am I missing ? (Or... how can I use its functions without linking to a lib and include a header ?)
Note: I assume the structs and typedefs do not need to be exported... true ?
Update: as I wrote in comment, the project did create a lib when I imported it into a different solution and erased all the debug folders... I have been "Build -> Clean Solution" between tries but I suppose something did not get cleaned ...
So the true reason for not getting a lib created was (my guess) that, while experimenting with the code and before adding the definition for MYDLL_EXPORTS, files where created that did not get cleaned... I will always delete the build folders before trying again, in the future.
I checked with a small test project in VS2013. It produced .lib files for both my DLLs in the Debug directory. This means that if the setup is not screwed up, using default settings you should have implib after building the DLL.
In fact, you need .lib file only if you want to distribute your dll to customers. If you want to use this dll in the same solution by other projects, do the following:
Select project where you want to import functions.
On the top menu click PROJECT->References....
Click button "Add New Reference" at the mid bottom.
Select dlls that you want to import from.
Close all dialogs with OK.
Rebuild your solution.
Structures cannot be exported. They are communicated to other binaries using header files. You can export only function entry points (including class member functions) and static data fields. You should include your header both into your dll code and and all applications that use your DLL. The #ifdef MYDLL_EXPORTS has exactly this purpose.
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
After a day of banging my head against the wall both literally and metaphorically, I plead for help:
I have an unmanaged C++ project, which is compiled as a DLL. Let's call it CPP Project. It currently works in an unmanaged environment. In addition, I have created a WPF project, that shall be called WPF Project. This project is a simple and currently almost empty project. It contains a single window and I want it to use code from Project 1. For that, I have created a CLR C++ project, which shall be called Interop Project and is also compiled as a DLL.
For simplicity I will attach some basic testing code I have boiled down to the basics.
CPP Project has the following two testing files:
tester.h
#pragma once
extern "C" class __declspec(dllexport) NativeTester
{
public:
void NativeTest();
};
tester.cpp
#include "tester.h"
void NativeTester::NativeTest()
{
int i = 0;
}
Interop Project has the following file:
InteropLib.h
#pragma once
#include <tester.h>
using namespace System;
namespace InteropLib {
public ref class InteropProject
{
public:
static void Test()
{
NativeTester nativeTester;
nativeTester.NativeTest();
}
};
}
Lastly, WPF Project has a single window refrencing Interop Project:
MainWindow.xaml.cs
using System;
using System.Windows;
using InteropLib;
namespace AppGUI
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
InteropProject.Test();
}
}
}
And the XAML itself has an empty window (default created).
Once I am trying to run the WPF project, I get the following error:
System.Windows.Markup.XamlParseException: 'The invocation of the constructor on type 'AppGUI.MainWindow' that matches the specified binding constraints threw an exception.' Line number '3' and line position '9'. ---> System.IO.FileNotFoundException: Could not load file or assembly 'InteropLib.dll' or one of its dependencies. The specified module could not be found.
at AppGUI.MainWindow..ctor()
Interestingly enough, if I do not export the class from CPP Project, I do not get this error. Say, if i change tester.h to:
#pragma once
class NativeTester
{
public:
void NativeTest()
{
int i = 0;
}
};
However, in this case I cannot use my more complex classes. If I move my implementation to a cpp file like before, I get unresolved linkage errors due to my not exporting my code. The C++ code I want to actually use is large and has many classes and is object oriented, so I can't just move all my implementation to the h files.
Please help me understand this horrific error I've been trying resolve without success.
Thanks.
This went wrong right from the start, your tester.h file is not correct. The class should only have the __declspec(dllexport) attribute when you are building the tester project. Any other project that uses the DLL must see the class with the __declspec(dllimport) attribute. Start fixing this by using a macro in tester.h:
#undef EXPORTED
#ifdef BUILDING_DLL
# define EXPORTED __declspec(dllexport)
#else
# define EXPORTED __declspec(dllimport)
#endif
class EXPORTED NativeTester {
// etc..
};
And in your tester project, use C/C++, Preprocessor, Preprocessor Definitions and add BUILDING_DLL.
Next thing is to make sure that the DLL is being stored in the right directory. Which is what the exception is complaining about, it can't find the DLL. The build directory for C++ projects is Debug but for WPF projects it is bin\Debug. Fix that by changing the General + Output Directory setting, make it $(SolutionDir)$bin\(ConfigurationName).
Build the C++ project and verify that you can find the DLL back in the Solution's bin\Debug directory. And check that you also have the .lib file, you'll need that when you build the C++/CLI project. As an extra verification step, run Dumpbin.exe /exports foo.dll from the Visual Studio Command Prompt and check that you indeed see the class getting exported.
The C++/CLI project next, you need to change the Output Directory setting the same way. Add the .lib file to the linker's Additional Dependencies properties. You'll get the kind of linker errors you were talking about if you skip that step. Build it and verify that you get the DLL in the correct bin\Debug directory again.
Repeat these changes for the Release configuration.
Set the project dependencies, the WPF project depends on the C++/CLI project. The C++/CLI project depends on the C++ project. This ensures the projects are getting built in the right order.
You should now have a good shot at using these DLLs in your WPF project.