I'm going to write a simple algorithm provider under CNG (Cryptography Next Generation), exactly an user-mode Hash Provider.
According to the instruction in CNG Development Kit Help "A hash provider must implement the GetHashInterface function and export it by name".
To implement an algorithm provider, I need to include the "bcrypt.h" file from the CNG Development Kit. This file also define the interface for GetHashInterface function but WITHOUT an export directive, exactly:
__checkReturn
NTSTATUS
WINAPI
GetHashInterface(
__in LPCWSTR pszProviderName,
__in LPCWSTR pszAlgId,
__out BCRYPT_HASH_FUNCTION_TABLE **ppFunctionTable,
__in ULONG dwFlags);
If I redefine the function in my header file as an exportable function, for example
#ifndef __CngHashProvider
#define __CngHashProvider
///////////////////////////////////////////////////////////////
#ifndef EXPORT
#define EXPORT extern "C" __declspec(dllexport)
#endif
EXPORT NTSTATUS WINAPI GetHashInterface(
__in LPCWSTR pszProviderName,
__in LPCWSTR pszAlgId,
__out BCRYPT_HASH_FUNCTION_TABLE **ppFunctionTable,
__in ULONG dwFlags
);
////////////////////////////////////////////////////////////////
#endif __CngHashProvider
I should get an error message:
Error C2375 'GetHashInterface': redefinition; different linkage
If I remove the EXPORT directive (or remove the whole of interface predefinition for the function), the error message should disappear, but the function can not be exported from my DLL.
So please help me, telling me the way to solve the problem to export the needed GetHashInterface function.
At the moment I "found" a way to solve the problem.
I coppied the file bcrypt.h from the CNG Development Kit to my project folder and then removed the definition of the GetHashInterface function. My project should include the modified header file, but not the original one.
I don't know is it a right way, but it works for me.
You can use .def file without the need to edit bcrypt.h. In Visual Studio: Add->New item->Code->Module-definition file.
Just add to this file:
LIBRARY "yourlibraryname"
EXPORTS
GetHashInterface = GetHashInterface
Related
I have got a library which was made for a desktop windows project. It is done in MFC VC++ by somebody else, and it works correctly. I will use one particular function from the library as an example for explaining the situation.
The example function goes like this:
CString GetFulPath(); // .h file
In the cpp file,
CString CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath); //ITEMIDLISTからパスを得る
path.ReleaseBuffer();
}
return path;
}
Now, I can include this library in my project and do something like:
CwFolderBrowser cFolderBrowser;
if(cFolderBrowser.ShowDialog() == TRUE)
cPath = cFolderBrowser.GetFullPath();
This will show a folder browser dialog and let me choose a folder. It works fine on desktop windows.
Currently, I am working on Windows CE device. We have converted the library for use with Windows CE by removing unsupported functions and stuff. The library compiles and builds correctly without errors.
Next, I create an MFC Smart Device project, include the converted library, its h file and lib files and set the proper directories for dlls. The project builds fine. I can #include the library's h file properly too.
The problem arises as soon as I call the GetFullPath function:
cPath = cFolderBrowser.GetFullPath();
It gives me an unresolved external link error! The Intellisense does show this function in its list and I can choose it and everything. But in vain.
Strangely, If I modify the library and change GetFullPath()'s signature as below,
LPCTSTR GetFulPath(); // .h file LPCTSTR instead of CString
In the cpp file,
LPCTSTR CwFolderBrowser::GetFullPath() // Return type changed to LPCTSTR
{ // instead of CString
... // Body modified accordingly
}
then, the unresolved external Link error disappears and it works!
I am stumped about this strange behaviour, because, I can use CString normally in the MFC Smart Device project and there are no errors. The link error shows up only when I try to call functions from the library (and other such libraries) dll. At the same time, BOOL, int etc. seems to have no problems as function return types.
Ofcourse, I can go through each library and change every instanceof a CString return to LPCTSTR, but that would be a very big change. I would like to know why CString works fine in project as well as dll when on desktop, while, on Win CE, it works in the project but not i the DLL (At the same time, the DLL itself compiles fine without errors wether it uses CString or LPCTSTR!).
So, basically, I would like to keep the function CString if possible, and would like to know the reason why this happens. The exact same error also happenes in other libraries too.
Any help is appreciated. Thank you.
UPDATE:
I saw a page on ATL & MFC 7.0 which said about using the /Zc:wchat_t option. I have checked the Dll project as well as my application. Both use the same option of 'Treat wchar_t as Built-in type' as Yes. So, that option matches up.
Further, as I mentioned above, changing the function return to LPCTSTR works. The error disappears. Everything is going fine until I convert the returned LPCTSTR back to CString. The CString turns out as empty/Null. This happens both inside the dll code itself, as well as in my application code too.
UPDATE2:
Thanks to Michael and Cody, I changed the function to LPCTSTR and made sure that the values were not going out of scope before I could use them like they suggested. Now the empty/Null problem is solved and I can get the path values properly.
The problem that remains is that I have to convert all the CString functions to LPCTSTR, which is not exactly feasible. I would like to keep the functions as CString.
This is a classic problem and has been asked often here on SO.
This cannot work:
LPCTSTR CwFolderBrowser::GetFullPath()
{
CString path;
if(this->M_pIDLIST!=NULL)
{
LPTSTR fullPath=path.GetBuffer(MAX_PATH);
::SHGetPathFromIDList(this->M_pIDLIST, fullPath);
path.ReleaseBuffer();
}
return (LPCTSTR)path; // << here you return a pointer to the zero
// terminated string in the path object,
} // but path will be deleted as soon as it goes
// out of scope
Maybe in some cases the function appears to work because the memory of the deleted CString object has not yet been overwritten.
You should do this (no error treatment here for simplicity):
LPCTSTR CwFolderBrowser::GetFullPath(TCHAR *pathbuffer)
{
if(this->M_pIDLIST!=NULL)
{
::SHGetPathFromIDList(this->M_pIDLIST, pathbuffer);
}
return (LPCTSTR)pathbuffer;
}
...
// call like this
TCHAR pathbuffer[MAX_PATH];
GetFullPath(pathbuffer);
I just bought a device that comes with a dll file. I want to use Visual C++ to program the device. How do I load the .dll file into my project?
A DLL is a library file that contains compiled program logic, just like an EXE. You can't execute it alone, but like an EXE file you can't just 'load' it into your project either.
You will need to use functions like Load Library to load the library, and then GetProcAddress to find a function you want to call.
Edit:
After you clarified your question in the comments you are trying to write a windows program instead of a program you run on your device.
I wrote some sample code to show you how to start:
#include <windows.h> // This is a windows header file. The functions I mentioned above are declared here
#include "mpusbapi.h" // This is the header file supplied. It declares the function prototypes that are defined in the DLL
int main(int argc, char* argv)
{
// Try to load the library
HMODULE mpbusDLL = NULL;
mpbusDLL = LoadLibrary(L"mpusbapi.dll");
if (mpbusDLL != NULL) {
// If the library could be loaded, then load the functions using GetProcAddress()
// Load the function 'MPUSBOpen' from the DLL
MPUSBOpen = (HANDLE(*)(DWORD, PCHAR, PCHAR, DWORD, DWORD)) GetProcAddress(mpbusDLL, "_MPUSBOpen");
...
MPUSBOpen(...);
}
}
This C code will load your libary and then attempt to load the function MPUSBOpen, which is implemented in your DLL.
You will need to load the other functions defined in your header file the same way (at least if you want to use them).
How do I export the methods of a native class defined in a C++/CLI project? Here's what I have:
The .h file:
#pragma once
#ifdef COMPILE_PRODUCER_LIB
#define PRODUCER_LIB_EXPORT __declspec(dllexport)
#else
#define PRODUCER_LIB_EXPORT __declspec(dllimport)
#endif
public class PRODUCER_LIB_EXPORT MySecondNativeClass {
public:
MySecondNativeClass(int val);
int getValue() const;
private:
int m_value;
};
The .cpp file:
#include "stdafx.h"
#include "MySecondNativeClass.h"
MySecondNativeClass::MySecondNativeClass(int val) {
this->m_value = val;
}
int MySecondNativeClass::getValue() const {
return this->m_value;
}
Using this class in the same project works fine, but using it in another (C++/CLI) project gives me "unresolved external symbol" linker errors. (COMPILE_PRODUCER_LIB is a preprocessor definition defined only in the project that contains the class.)
I've created a small solution (for Visual Studio 2010) that shows the problem (download at the end of this page). There, the native class MySecondNativeClass is defined in the project "ManagedProviderLib" and is being used in "ExternalTestClass.cpp" (in project "ManagedExternalLib").
Your DLL project creates a .lib file in the build directory, the DLL's import library. You need to specify that .lib file in the other project, Linker + Input, Additional Dependencies setting.
Note that Add Reference cannot work, the assembly metadata only contains definitions for managed classes. Your class is native C++, not managed. Also make sure that your .cpp file is compiled without /clr in effect. The C++/CLI compiler will happily translate native C++ classes to IL but that is not very efficient. You can control this within the source code file with #pragma managed.
So I just began to try my hand at emulation after years of putting it off and not knowing where to start and I have managed to successfully write my first emulator! Now I am organizing my code in so that I can reuse the code to emulate other systems. I've been toying with the idea of having a shared frontend "platform handler" of sorts that I will compile as my executable whereas I will compile my emulated system code into dlls that the platform handler will use to identify what is available and instantiate from. This would allow me to separate my code into different projects and to leave the option open of using a bulkier front-end with more features or a streamlined "game only" and to share the same dlls between them rather than make two different solutions.
I know how to compile dlls vs executables but I don't know how to link the executable to the custom dll in such a way that I can instantiate a class from it. I'm not even sure what I'm trying to do is technically possible. Do the dll classes need to be static? I've never coded anything like this before or even done much with custom dlls so any help or ideas would be appreciated. I'm using Visual C++ 2010 by the way. Thanks in advance for any advice anyone may have.
You don't really have to do much different. Just export your classes from the dll like you do for functions. In your app, include the header and link to the generated lib like you usually do. See this page: http://msdn.microsoft.com/en-us/library/81h27t8c%28v=vs.80%29.aspx
Example.h
#ifdef DLL_EXPORT
#define EXPORT_API __declspec(dllexport)
#else
#define EXPORT_API __declspec(dllimport)
#endif
class EXPORT_API Example
{
public:
Example();
~Example();
int SomeMethod();
};
int EXPORT_API ExampleFuncion();
Example.cpp
#include "Example.h"
Example::Example()
{
// construct stuff
}
Example::~Example()
{
// destruct stuff
}
int Example::SomeMethod()
{
// do stuff
return 0;
}
int EXPORT_API ExampleFunction()
{
return 0;
}
In your dll project, define DLL_EXPORT and build. You will get a .lib and .dll output. In your main project where you will be using the dll you do not have to do anything except include the header and link against the .lib. Do not define the DLL_EXPORT symbol in your main project and be sure the .dll is somewhere your application can find it.
If you really want to get clever, this problem is screaming for the factory design pattern. If you design your interface well enough, you can have your dlls register their implementation with your application when they are loaded. You can extend forever without even rebuilding your main executable.
Precondition
environment : VC2005
I encountered this problem when discovered circular dependency in my project(two dll references each other), so divide either of one dll to two dll's.
explain with example :
typedef struct { <br>
char myFileName[MAX_PATH];
} MyStructure;
Before :
MyHeader.h
MyStructure globalStruct;
After:
MyCommon.h
#ifdef _MYGLOBAL_
#define API __declspec(dllexport)
#else
#define API __declspec(dllimport)
#endif
API extern MyStructure globalStruct;
MyGlobal.c
API MyStructure globalStruct;
MySpecific.c
API MyStructure globalStruct;
failed code after changed: (this code run in specific dll)
handle = LoadLibrary(globalStruct.myFileName);
I confirmed globalStruct.myFileName values are same(at lease real words).
I can't access the value directly with debugger after changed. so, to see value in debugger, I copyed to temp local char[] variable. And then, I found before value and after value are different in tailing dummy char's.
before:
d:[my path] '0'(char end null) '0' '0' ...
after:
d:[my path] '0'(char end null) '-3' '-3' '-3' ...
thank you for your reading.
self-solved my problem.
This is because dll does not re-compiled after my circular dependency removal work.
So, this problem is not related import/export global variable but dll re-compile issue.
Sorry for my ugly question.