so here's my issue. I have a DLL that is referenced by an application (both of which I'm writing). The DLL should declare a method, called AppMain, and the application should define this method. Before I started using DLLs I was using a LIB file and the extern keyword. My code used to look like this:
The referenced assembly
extern bool AppMain(void* input);
The application referencing the assembly
#pragma comment( lib, "TheReferencedAssembly.lib" )
bool AppMain( void* input )
{
// Awesome stuff
}
Now that I'm using a DLL, I've droppped the #pragma comment part and just referenced the assembly and included a header that contains the declaration, but I keep getting the old unresolved reference error.
Any help here would be greatly appreciated. Thanks!
Related
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");
}
I've always found it a bit of a pain that you have to use LoadLibrary() and define function pointers when wanting to make use of a DLL, it just feels a bit archaic when so much is automated now days. So when I stumbled across a forum post explaining that the VS auto-generated lib file that always (in my experience) gets compiled alonside your DLL can be used to save yourself the hassle, as a sort of auto-import mechanism, I figured I'd put it to the test.
I created two very minimal projects to test this, but it doesn't appear to be working.
The code in its entrirety for the DLL:
extern "C"
{
__declspec(dllexport) int get10()
{
return 10;
}
}
And for the exe (an otherwise empty Win32 console app):
#include <Windows.h>
#pragma comment(lib, "Kernel32.lib")
#pragma comment(lib, "dll1.lib")
__declspec(dllimport) int get10();
int main(int, char**)
{
int x = 0;
if (LoadLibrary(L"dll1.dll") != NULL)
{
x = get10();
}
return 0;
}
dll1.dll and dll1.lib are local and visible to the project, but when I go to link it get10() is unresolved. If I remove the call to this it builds and runs and the LoadLibrary() call succeeds.
I also tried copying across the dll1.exp, just clutching at straws really, but that didn't help either.
Is what I'm trying to do actually valid?
By the way I appreciate you'd usually just use a lib file proper, it just grabbed my curiosity for circumstances where you might have these dll and "reduced" lib files but not have the source to compile a regular lib file.
You either link as static, or as dynamic.
So, in essence, you need __declspec(dllexport) only if you're loading the function at runtime by name. Read some of this, for example.
As mentioned here, regarding __declspec(dllexport):
This convenience is most apparent when trying to export decorated C++ function names. Because there is no standard specification for name decoration, the name of an exported function might change between compiler versions. If you use __declspec(dllexport), recompiling the DLL and dependent .exe files is necessary only to account for any naming convention changes.
I've read several articles here on name mangling/decoration and keep running into inconsistencies so I thought I would ask a pretty focused question and see what happens.
I am trying to work my way up the learning curve to eventually be able to create a dll in VS2013 that is usable by code generated on a very old Borland C++ compiler. The first step is to build an exe and dll in VS2013 that can "talk". I want undecorated function names. So I have created a dll with one exported function.
extern "C" __declspec(dllexport) int __cdecl BasicFileOpen(void);
My limited understanding is:
extern "C" means no decoration
__declspec(dllexport) means export the function
__cdecl specifies the calling signature (how parameter get put on the stack, etc)
When I examine the dll using DependencyWalker or Dumpbin /EXPORTS, the function name is undecorated. Yay.
Here is the code in the exe that attempts to call the exported function in the dll:
void CCallsCIDdllDlg::OnBnClickedOk()
{
int iRetVal = BasicFileOpen();
// TODO: Add your control notification handler code here
CDialogEx::OnOK();
}
However, when I try to build the exe, I get a linker error.
error LNK2019: unresolved external symbol _BasicFileOpen referenced in function
"public: void __thiscall CCallsCIDdllDlg::OnBnClickedOk(void)"
(?OnBnClickedOk#CCallsCIDdllDlg##QAEXXZ)
Note that the exe mentions _BasicFileOpen.
I am puzzled by this.
I have correctly pointed at the lib file produced by the dll build.
I am including the header file for the dll function in the exe.
Why doesn't the linker understand the name of the exported function?
Why does it think the function name is decorated?
BTW using a .def file does not seem to make any difference.
Any comments are appreciated.
MBB
I have created one static "C" library using VS.
I am using the same library file for another VS console C application its working fine but when I am working with windows forms app it's not working.
Referred so many queries in this forum but didn't get the Help.
Is there any naming conventions to call the static library functions from the Windows forms Managed c++ ?
Getting Errors Like this
error LNK2028: unresolved token (0A000032) "enum STATUS __clrcall
xyz(unsigned char)" (?xyz##$$FYM?AW4STATUS##E#Z) referenced in
function
__catch$?button3_Click#Form1#Myapp##$$FA$AAMXP$AAVObject#System##P$AAVEventArgs#4##Z$0
But I should use the same static library for both console and windows application.
The linker error message gives a strong hint what it going wrong. Note the __clrcall calling convention for the undefined symbol, it tells you that the compiler thinks that these are "CLR" functions. Managed code, of course they are not, they are __cdecl. There's more, the names are also mangled. Note the "##$$FYM?AW4STATUS##E#Z" curses in the name. Which tells you that the compiler thinks they were written in C++ instead of C.
You'll have to explicitly tell the compiler about this, the .h file isn't compatible enough. Which you do like this in your C++/CLI source code file:
#pragma managed(push, off)
extern "C" {
#include "yadayada.h"
}
#pragma managed(pop)
The #pragmas temporarily turn off managed code compilation mode so the compiler will now assume these are unmanaged function declarations. The extern "C" {} wrap around the #include tells the compiler that the .h file contains C declarations.
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).