How to use functions exported from DLL in C++? - c++

I create two projects in VC++ Express 2010, one is DLLTest, the other is CODETest.
In DLLTest, declare and define a function func() as follows:
__declspec(dllexport) void func() {...};
Build DLLTest project successfully, DLLTest.dll and DLLTest.lib files created.
In CODETest, i want to use the exported function as follows:
#include "DLLTest.h"
int main()
{
...
func();
...
return 0;
}
Error occurs when build CODETest project--->"unresolved external symbol "void __cdecl letterList(void)" , but when i add DLLTest.lib into directory of CODETest project, build process successfully.
I dont know why? Thanks for help.

This seems all pretty unlikely, especially the part where "func" transformed into "letterList". Nevertheless, you have to tell the linker to also link the import library of the DLL so that it can resolve identifiers that are imported from that DLL. The easiest way to do that in MSVC is:
#include "DLLTest.h"
#pragma comment(lib, "dlltest.lib")
in CodeTest.cpp. The #pragma does the same thing as the linker's Additional Dependencies setting.

Related

Visual Studio C++ static lib function exposing problem

I have created example of using static libraries. The goal is this functionality:
DllTestFunctDll.dll links static_lib.lib (contains fnStaticLibrary())
example.exe links DllTestFunctDll.dll (contains dllTestFunct())
main() calls directly fnStaticLibrary() and dllTestFunct().
dllTestFunct() calls directly fnStaticLibrary().
I don't understand one thing, this works only if fnStaticLibrary() is inside same project as main() and dllTestFunct().
If I create another solution that
DllTestFunctDll.dll links also static_lib.lib (contains fnStaticLibTest())
main() newly also calls directly fnStaticLibTest().
dllTestFunct() newly also calls directly fnStaticLibTest().
dllTestFunct() is able to call fnStaticLibTest() and main() is unable to call fnStaticLibTest() due to linker. But I am able to call fnStaticLibTest() inside dllTestFunct().
I used dumpbin to see what functions are exported:
dumpbin /EXPORTS "C:\\path\\DllTestFunctDll.dll"
Output:
ordinal hint RVA name
1 0 00001000 ?dllTestFunct##YAXXZ = ?dllTestFunct##YAXXZ (void __cdecl DllTestFunct(void))
2 1 00001070 ?fnStaticLibrary##YAXXZ = ?fnStaticLibrary##YAXXZ (void __cdecl fnStaticLibrary(void))
You can see that fnStaticLibTest() is missing inside the output.
In both static lib projects I export function by "__declspec(dllexport) ".
I assume that the problem is inside the Visual Studio. Do you know how to solve it?
Thank you in advance for your answers.
CODE (VS17 solution) LINK: https://github.com/Ales5475/StaticLibProblemExample
An object module is added from a .lib, if it is required. If the dll does not call (or reference) any item in a compilation unit (c/cpp file), it won't be added to the dll
This behavior is important for libraries, as it ensures that when linking against the C/C++ runtimes, then you don't import the whole of the libraries. Just those which are required.
In your case you have a DLL which doesn't require the test function, and a .EXE which expects the DLL to have it. There is no visible requirement for the test function when the DLL is being built.
A DLL has explicit exports. Either
__declspec(dllexport)
or a .DEF file with exports. In this case, it appears that the static lib doesn't know if it is in a DLL or the EXE, so isn't decorated with declspec(dllexport) the best solution is for the .def file for the DLL to explicitly export the function.
The code in StaticLibTest.h
__declspec(dllexport) void fnStaticLibTest();
is inconsistent with the code in StaticLibTest.cpp
void fnStaticLibTest(){
This will not cause the function to be exported. In general include a file which declares a function / structure to ensure it is consistent.
The correct form is
void __declspec(dllexport) fnStaticLibTest(){
and
void __declspec(dllexport) fnStaticLibTest();
Otherwise you are adding the attribute to the void.
Here is the snippet I did use #pragma comment successfully.
DLL:
__declspec(dllexport) void DllTestFunct();
...
#pragma comment(linker, "/export:fnStaticLibTest")
void DllTestFunct() {
fnStaticLibrary();
fnStaticLibTest();
printf("Hello world (Dynamic library)!\n");
}
DLL's dependency:
Header Folder:
XXX\StaticLibTest\StaticLibTest;
XXX\MainProgram\StaticLibrary;
DLL Folder:
XXX\StaticLibTest\x64\Debug;
XXX\MainProgram\x64\Debug;
DLL input:
StaticLibTest.lib;
StaticLibrary.lib
Static Lib:
extern "C" void fnStaticLibTest();
...
extern "C" void fnStaticLibTest() {
printf("Hello World! (Static library from another project)\n");
}

Unresolved Symbol Errors for C++/CLI dll in C++ Project

I am trying a very simple implementation of a C++/CLI wrapper to allow legacy C++ code to reference .Net code, as described here. I am getting stuck just trying to get my basic C++/CLI unmanaged (native) objects linked, without even including any managed/IL/.Net code.
My question is, following along with this basic setup and what I describe below, am I right to be very confused about these errors? Are there some considerations that I'm missing? Maybe the answer is that this should work, so it's not clear what's wrong. That's still helpful. A similar working example would be great.
Unresolved Symbol Errors
Error LNK2019 unresolved external symbol "__declspec(dllimport)
public: __thiscall Wrapper::Test::Test(void)"
(__imp_??0Test#Wrapper##QAE#XZ) referenced in function _main NativeApp
Error LNK2019 unresolved external symbol "__declspec(dllimport)
public: __thiscall Wrapper::Test::~Test(void)"
(__imp_??1Test#Wrapper##QAE#XZ) referenced in function _main NativeApp
I've reviewed related questions on SO without any luck. I've got my dll header included in the client C++ project, my project reference to the C++/CLI wrapper dll, and my define statements for import/export. My very simple code is shown below. I am not using any MFC. I am using VS2017. DumpBin.exe /exports shows export symbols that seem to match what the linker error says are missing.
1 0 000010D0 ??0Test#Wrapper##QAE#XZ = ??0Test#Wrapper##QAE#XZ (public: __thiscall Wrapper::Test::Test(void))
2 1 000010E0 ??1Test#Wrapper##QAE#XZ = ??1Test#Wrapper##QAE#XZ (public: __thiscall Wrapper::Test::~Test(void))
3 2 000010C0 ??4Test#Wrapper##QAEAAV01#ABV01##Z = ??4Test#Wrapper##QAEAAV01#ABV01##Z (public: class Wrapper::Test & __thiscall Wrapper::Test::operator=(class Wrapper::Test const &))
Here's the basic code...
NativeApp.exe (project)
NativeApp.cpp (File)
#include "stdafx.h"
#include <iostream>
#include "Wrapper.h" //From additional includes directory
int main()
{
std::cout << "Program Started" << std::endl;
Wrapper::Test shell = Wrapper::Test::Test(); //Use dll
std::cin.get();
return 0;
}
Reference to Wrapper
Wrapper.dll (Project)
Wrapper.cpp (File)
#include "Wrapper.h"
#pragma unmanaged
namespace Wrapper {
Test::Test() {
}
Test::~Test() {
}
}
Wrapper.h (File)
#pragma once
#ifdef WRAPPER_EXPORTS
#define WRAPPER_API __declspec(dllexport)
#else
#define WRAPPER_API __declspec(dllimport)
#endif
#pragma unmanaged
namespace Wrapper {
class WRAPPER_API Test {
public:
Test();
~Test();
};
}
I was under the impression that the project reference took care of any additional dependency settings behind the scenes. Apparently, that is not the case. The .lib file needed to be added as an additional dependency, as is described here. However, as described by this Microsoft document, everything worked without additional dependencies when I was using non /clr dlls, so I'm not sure why the additional dependency was only required for my CLR reference. Clearly, I need to read up on this some more.
In any case, my C++ client project requirements are listed below. I was missing the second requirement. Also, here is an example project that helped me diagnose the problem.
1.) Add project reference
2.) Add the .lib file as an `Additional Dependency.
[Optional] Use Additional Library Directories
3.) #include .h file in code where appropriate
[Optional] Use additional include directories
EDIT: Why the additional dependency was required, and alternative option
As noted above, I was getting hung up on why the .lib additional dependency was required for the /clr dll but not for the non-clr dll. The answer is because a /clr project is configured by default to ignore import libraries. So when the project gets referenced by another C++ project, the project reference ignores import libraries. Changing this setting (Linker > General > Ignore Import Libraries) to "No" in the /clr dll project solves the issue so that the additional dependency is not required and the project reference works the same as the non-clr C++ dll.

error LNK2001: unresolved external symbol

I have two VC++ projects inside a sln file in visual studio 2010. I want to use a_flag in the file of another project, is this possible what i am doing below ?
Project 1:
**sample_header.h**
#ifndef SAMPLE_HEADER_API
#define SAMPLE_HEADER_API __declspec(dllimport)
#endif
extern SAMPLE_HEADER_API int a_flg;
**file1.cpp**
#define SAMPLE_HEADER_API __declspec(dllexport)
#include "sample_header.h"
// Intialization of external
int a_flag = 15;
void m_func()
{
int i = 0;
}
Project 2:
**file2.h**
#include <stdio.h>
**file2.cpp**
#include "file1.h"
#include "sample_header.h"
// provided path of "sample_header.h" in additional include directory as well
void main()
{
if(a_flag > 0)
{
std::cout << "FLAG" ;
}
}
I set project1 as a DLL, project2 as an EXE project.
In linking, I am getting this error :
error LNK2001: `unresolved external symbol "__declspec(dllimport) int a_flg" (__imp_?a_flg##3HA)` in file2.cpp
I have read Microsoft page here about the DLL creation and linking but no idea how to resolve this external symbol error.
Thanks !
You need to set the project that creates your .dll to also generate the .lib file (an import library).
A quick description of the linkage should be something like this :
DLL Dependency Project -> dependecy.dll + dependency.lib
Main Project -> depends at runtime to depedency.dll , depends at link time to dependency.lib.
In other words, your .dll is just another binary that exposes some function signatures.
At runtime you can choose for either c linkage which involves querying the dll for the exposed functors/variables via name (the hard way, but useful when you don't have the .dll source code at hand) or use a more elegant way where you link the generated static library with your main.
When using the 1st approach, you will need to treat inside your code if you cannot find a certain .dll .
When using the 2nd approach, your binary will know that it depends on a certain .dll when you try to run it .
Here's an answer you will find very useful :
How do I build an import library (.lib) AND a DLL in Visual C++?

Unable to export functions from C++ DLL

I need to create a C++ MFC DLL using Visual Studio 2008. To do this I created a DLL MFC Win32 Console project in Visual Studio and made a function that creates an object and uses its method to print a string to the screen. Kind of like this:
__declspec(dllexport) void Foo(void);
where:
void Foo(void){
print* obj = new print;
obj->testPrint();
return;
}
void print::testPrint(void){
printf("Bar\n");
return;
}
It compiles successfully and generates the DLL, but when I try to use it I always get:
"error LNK2019: unresolved external symbol "void __cdecl Foo(void)"
I tried using Dependency Walker and it doesn't show any function up in the DLL. Am I doing something wrong? I've searched a lot and still got no conclusions from what may be happening.
Sounds like you may not have included the header file which specifies the export in any cpp file. Remember that the cpp files are the only ones actually compiled. So make sure you include the header with the __declspec(dllexport) void Foo(void); in at least one cpp file. Also make sure that your project Linker->Input settings don't have a 'Module Definition File' (def) file specified.
Don't bother trying to link to the DLL until dependency walker shows that something is actually exported.
Windows defaults to cdecl so you need to make explicit that it's exported declspec in the caller - or export it from the DLL as cdecl instead.
You need to export the symbol explicitly from CPP file also:
__declspec(dllexport)
void Foo(void)
{
print* obj = new print;
obj->testPrint();
return;
}
The specification in header is merely for the client (EXE), and a hint for the linker from the server (DLL).

LNK2019 when converting an app to use DLLs

(Re-written for clarity)
I have a multi-project solution that I am looking to convert from using .lib to .DLL files. I have created my __declspec macros and applied it to every class except for those in the project that creates the final .exe. The linker is throwing a fit on just about everything, however. I have set up to ignore errors about exporting templated objects.
One example is this:
error LNK2019: unresolved external
symbol "__declspec(dllimport) public:
void __thiscall
Rail::SetNextRail(class Rail *)"
(__imp_?SetNextRail#Rail##QAEXPAV1##Z)
referenced in function "public: static
void __cdecl
MyUtilities::CreateBezierRails(int,class
MyVector *,class std::vector > &)" (?CreateBezierRails#MyUtilities##SAXHPAVMyVector##AAV?$vector#PAVRail##V?$allocator#PAVRail###std###std###Z) MyUtilities.obj
Unresolved external symbol on my __declspec(dllimport)? That doesn't seem right. It is getting placed by a macro such as:
#ifdef MYAI_EXPORT
#define DECLSPECAI __declspec(dllexport)
#else
#define DECLSPECAI __declspec(dllimport)
#endif
Basically, what gives? Why am I getting these errors and how can I fix them? Thank you to everybody who has tried to help thus far, but I am still stuck with this.
Are you linking against MyRenderer.lib?
Do you export your functions and classes using
__declspec(dllexport)
and import them using
__declspec(dllimport)
? If not, you will have to do this. In your header, during compiling the DLL, you will need to have the dllexport clause, and when using the header in other DLLs or EXEs, you will have to use the dllimport clause. You can easily do this by defining a macro like
// set this in preprocessor options for the DLL
#ifdef MYDLL
# define MYDLL_IMPORTEXPORT __declspec(dllexport)
#else
# define MYDLL_IMPORTEXPORT __declspec(dllimport)
#endif
class MYDLL_IMPORTEXPORT MyClass {};
Well its saying that it found a declaration but no implementation. Are you sure you are compilnig the file with the function implementation in it? Have you remembered to put the MyRenderer:: before the DrawVertices call? Are you sure you are linking both the libraries into the executable?
Edit: When compiling a lib the library leaves a stub, effectively, saying I want this function when you can link it to me.
When you run the linker it runs through all the libraries looking for these stubs and "links" them to the actual implementation. Each cpp file you build compiles to an object file and this object file works in exactly the same way. If it can't link the stub to the actual function then you get a linker error such as you are seeing. Thus, either your renderer library is not being linked into the executable OR the implementation is missing something vital such as the MyRenderer::. Though if it was the latter i'd expect other problems to arise such as the lack of a IDirect3DDevice which, i assume, is a member of the class. Thus, most probably, you are failing to link the .lib in.
there are different configurations of DLLs.
staticly linked DLL - the implementations are in a DLL, and the definitions are in a .lib. You statically link to the .lib (which is kinda like a header), and the lib tells c++ how to call the function. this is probably what you want. make sure you get your __declspecs right.
dynamically linked DLL - everything is in the DLL, the definitions are also in the DLL, you need to manually set up function pointers to all the exported things, which are indexed by a string at runtime.
Google will help and made this CW so someone can make this answer suck less.
i also advise you to get DLLs working in a skeleton app.