Can I build executable as dll? - c++

I need to create a dll which contains stuff I have in my executable project in visual studio 2010. I realized instead of creating a dll project, I can just change the project configuration in project properties >> General >> 'configuration type' to 'dll' and it builds fine. It creates the dll. I added an additional .h/.cpp files which contains the export functions I want in the dll.
My first concern is that is this a legit dll? I am trying to load it using LoadLibrary() but I get error code 126 (The specified module could not be found) although the dll is in the project directory (same as executable). I am just wondering if it has to do with the fact it may not be a fully qualified dll for any reason? My exe project is MFC project.
** Update **
Thanks to the comments, I can now load the dll successfully - it was dependencies issue. However GetProcAddress() doesn't return valid pointer for the export function. The dumpbin /exports utility shows the dll has no export functions!
So I have added just .h/cpp files to the original project which has a simple dummy function for export right now.
__declspec(dllexport) int MakeDouble(int value);
I also included the header file in the app class just in case. I am wondering why does this function does't appear as an export? What do I have to do?

First:
__declspec(dllexport) int MakeDouble(int value);
Function declaration should have the same signature than the definition and, of course, the function must have a definition (at simple return 0; should work }
Second:
The exported function name is decorated with beautiful weird characters, you should use extern "C" (or the MS specific stdcall + the .def file).:
//.h
extern "C" __declspec(dllexport) int MakeDouble(int value);
//.cpp
extern "C" __declspec(dllexport) int MakeDouble(int value) {
return 0;
}
You should also check in project properties the option:
Configuration Properties -> C/C++ -> Code Generation -> Runtime Library
Make sure the value contains the word DLL.

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");
}

c++ import functions from dll - my dll doesn't export lib

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.

How do I get started writing DLLs in visual C++?

As the title says, although I guess what I really mean is "And using them later."
The Setup
I have followed this answer:
https://stackoverflow.com/a/13219631/696407
which creates a very simple dll
#include <stdio.h>
extern "C"
{
__declspec(dllexport) void DisplayHelloFromMyDLL()
{
printf ("Hello DLL.\n");
}
}
and I now have a dll compiled for release:
DllTest.dll
DllTest.exp
DllTest.lib
DllTest.pdb
When I run DllTest.dll through dumpbin, I find this line:
1 0 00001000 DisplayHelloFromMyDLL = _DisplayHelloFromMyDLL
USING THE DLL
To use that function in a new solution, I believe I must
Start a project in a new solution
Add the location of the DLL to the project under
Properties
Configuration Properties
Linker
General
Additional Library Directories
Add the .lib file under
Properties
Configuration Properties
Linker
Input
Additional Dependencies
and, having added the .lib there, the next step is... hvæt?
My code right now:
#include "stdafx.h"
int _tmain(int argc, _TCHAR* argv[])
{
while(1)
{
DisplayHelloFromMyDLL();
}
return 0;
}
but that doesn't work.
EDIT: I guess "doesn't work" is vague. The function gets Error: identifier "DisplayHelloFromMyDLL" is undefined
(Side question: Is my function called DisplayHelloFromMyDLL(); or _DisplayHelloFromMyDLL();?)
You need .h for compiler (use with #include, and add the folder to .h file as relative path to Configuration Properties > C/C++ > General > Additional Include Directories). Aside from .lib for linker you also need .dll to actually run the test application.
EDIT: There are two types of DLL's that you can make. First are C-like DLL's, with functions that have signatures as if they are written in C instead of in C++. All Windows DLL's (user32.dll, shell32.dll, version.dll) are built as such. The other are C++ DLL's, with functions that are part of the class. MFC and Standard C++ Libraries are such.
If you want to make a C++ DLL then you have to declare all classes that are part of interface as __declspec(dllexport) in your DLL project and __declspec(dllimport) in all projects that would use DLL. Usually the same file is used for this, but with a macro that is defined accordingly to one or the other. If you create a DLL from Visual Studio project template you would see this code.
Your case is actually the simpler case, as you want C-like DLL. You don't have to fiddle with this __declspec rubbish, but you need one additional .def file in DLL project. This should be the content of the .def file:
LIBRARY MyApi
EXPORTS
DisplayHelloFromMyDLL
Your header file (.h file) should look like this:
#pragma once
#ifndef HELLO_DLL_INCLUDED
#define HELLO_DLL_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
void DisplayHelloFromMyDLL();
#ifdef __cplusplus
};
#endif
#endif // HELLO_DLL_INCLUDED
__declspec(dllimport) tells the compiler that this function (or class) is defined somewhere else, and that linker will find it and link it. __declspec(dllexport) tells the compiler (and linker) that this function (or class) should be exported and be part of DLL interface. If class has neither of those then it's just a class that should be defined in the same project.
To consume your .dll you need two things, a header file and a .lib.
The header file is so that the compiler knows there is a function somewhere with the name DisplayHelloFromMyDLL(). At this point it doesn't matter where it is, just that you've told the compiler it's somewhere. The linker will take care of the where bit.
The .lib file is for the linker. It tells the linker that DisplayHelloFromMyDLL() lives in a .dll, and that (in your case) the name of the dll is DllTest.dll. When your program starts up the Windows loader will use this information to load the .dll into your process and will perform any address fixups to make sure that calling DisplayHelloFromMyDLL() in your application calls the function in your .dll.
You don't actually need the .dll in order to build your executable, only to run it.

A continued saga of C# interoprability with unmanaged C++

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.

About inconsistent dll linkage

How can I remove this link warning? You can see code segment that causes this warning.
static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
//bla bla
// Exported DLL initialization is run in context of running application
extern "C" void WINAPI InitGuiCtrlsDLL()
{
// create a new CDynLinkLibrary for this app
new CDynLinkLibrary(GuiCtrlsDLL);
// nothing more to do
}
warning C4273: 'InitGuiCtrlsDLL' : inconsistent dll linkage
I have also export and import definitions, like:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
The purpose of the preprocessor statements:
#ifdef _GUICTRLS
#define GUI_CTRLS_EXPORT __declspec(dllexport)
#else
#define GUI_CTRLS_EXPORT __declspec(dllimport)
#endif
is to make sure that the header file declares the class or function as __declspec(dllexport) in the .dll where it is defined, and as __declspec(dllimport) for any other .dll that might want to use it.
For this to work, _GUICTRLS must be defined when compiling the exporting .dll, and not defined for any other .dll. Generally you would expect _GUICTRLS to be defined in the project properties, under C/C++ -> Preprocessor -> Preprocessor Definitions.
The compiler error you are seeing usually happens because either _GUICTRLS is not defined for the project that is doing the export, or it is defined for multiple projects, usually resulting from cutting an pasting from one project to another. You will also see this if _GUICTRLS is defined in a header file that is included in multiple projects.
There are multiple possibilities:
1) static AFX_EXTENSION_MODULE GuiCtrlsDLL = { NULL, NULL };
You use AFX_EXTENSION_MODULE. This means that you are implementing an MFC extension DLL. For such extension dlls you have to define the preprocessor _AFXEXT. Set this in the C++ compiler settings of your Visual C++ project
see:
How To Use _declspec(dllexport) in an MFC Extension DLL: http://support.microsoft.com/kb/128199
AFX_EXTENSION_MODULE Structure: http://msdn.microsoft.com/en-us/library/sxfyk0zk.aspx
TN033: DLL Version of MFC: http://msdn.microsoft.com/en-us/library/hw85e4bb.aspx
2) It is likely that you have a duplicated definiton/declaration.
In addition to reading the warning message, pay attention to where it occurs if you have multiple projects as part of a workspace.
I wasted time looking for a problem in my DLL which was compiling and linking correctly. The workspace was also building the main application and my error was that I had inadvertently included a new (DLL) source file into the build file list of the application itself.
The main program requires the DLL header mynewdll.h to import things but does not require the source file mynewdll.cpp. (The code is brought in at run time with a DLL.) I have a habit of including header and code files into projects as a pair, and this is where I had gone wrong.
I would have detected the error much sooner if I had been alert and noticed that the DLL project linked with no errors and it was the main program that complained!
My DLL source code and project was error free and it was only the way I tried to build my executable that was faulty.
That warning is usually caused by a duplicate definition of a function with different use of dllimport. Are you sure you didn't do this?
[ CMake inconsistent dll linkage ]
I encountered the following issue + solution with the __declspec(dllexport) + __declspec(dllimport) :
# # #CMakeLists.txt
add_defintions(-DMYLIB=1)
# The above was the solution...
# (MYLIB is used in the standard ifdef + define MYLIB_EXPORT syntax)
# Below: seems to get overruled by other directory's headers:
set_source_files_properties( file1.h file2.h COMPILE_FLAGS "-DMYLIB=1")
This was annoying because a number of sources say to use the 'set source file properties' command to get better granularity but the doc is not clear on what happens to file1.h's declares when included from a different directory... better stick with add_definitions( -DMYLIB=1 ) for now!
To catch this problem: in your Foo.cpp file:
#include "export.h"
#if defined(MYLIB)
#if defined(OTHERLIB)
static_assert(0,"error, check your definitions!");
// OTHER depends on MY; can't have both of these flags being set!
#endif
#endif
struct OTHER_EXPORT foo
{
};
See that you are not defining the exported symbols in a different project. Also clean all the intermediate files by hand and recompile.
To elaborate the answer of damian with an example. I read it but didn't understand at first glance.
You have a shared library with a source file compiled in that contains the function. In a new project you use the library and in addition you compile also the source file to use the function (I forgot that it is already in the library). Within the library the functions label is exported, within the additional compiled source file the functions label is marked to be imported. That's the conflict.
In my case, error C4273 was caused by trying linking to .lib file from a DLL dynamic load tester app in Qt5 by msvc2017_64 toolchain. Removing the reference to .lib file by changing LIBS setting in .pro file have the problem solved.