I am trying to import a dll to a C# console application just to see if I can get a dll to work as a want, when trying this and exporting functions with C-code everything works fine and the functions can be imported in my C# application.
The problem starts when I try to add some kind of linkage to some QT methods in my unmanaged dll. I'm using DllImport to import the functions from the dll.
[DllImport("cDLL.dll", EntryPoint = "_Add#16")]
static extern double Add(double a, double b);
1 - This is how the unmanaged dll (don't look at the functionality of the code, this is just for testing purposes) looks like when it works fine.
main.cpp working
#include <stdexcept>
#include "Windows.h"
using namespace std;
extern "C" __declspec(dllexport) double __stdcall Add(double a, double b)
{
return a + b;
}
extern "C" __declspec(dllexport) const char* getText()
{
return "hello world";//returnBufferString.c_str();
}
BOOL __stdcall DllMain(HINSTANCE hInst, DWORD dwReason, LPVOID lpReserved) {
return TRUE;
}
2 - When I try to add a help function with some QT code, just an ordinary QString the DllImport starts throwing dllNotFoundException.dumpbin.exe shows all the exported functions as well after including the qt code...
main.cpp dllNotFoundException
#include <QString>
using namespace std;
class testa
{
public:
static char* test()
{
QString a = "hejsan";
return qString2Char(a);
}
static char* qString2Char(QString a)
{
return a.toUtf8().data();
}
};
This is called from the getText() function like this:
string returnBufferString;
extern "C" __declspec(dllexport) const char* getText()
{
returnBufferString = testa::test();
return returnBufferString.c_str();
}
When I try to access the dll from DllImport I get dllNotFoundException in the 2:nd part. How do I solve this? have I missed any dependencies or anything. My dll is build using msvc2010 compiler and the .pro file looks like this:
cDLL.pro
TEMPLATE = lib
CONFIG += dll
QT += core
# Input
SOURCES += main.cpp
I'm stuck...
It doesn't tell you exactly what DLL it cannot find. Which is almost surely not your DLL, it is one of the DLLs that QT requires. You'd have to copy them to the EXE folder as well. If you have no idea and can't find it in the Nokia documentation then you can find out with SysInternals' ProcMon utility.
However, in this scenario you surely want to link QT into your DLL since the odds that those DLLs can be shared are small. Use this SO question for guidance in setting up your QT project.
You need to put the DLL in the same folder as your executable.
See http://msdn.microsoft.com/en-us/library/windows/desktop/ms682586%28v=vs.85%29.aspx
Related
I'm looking for a way to remove some header file dependencies. I'm working on a test project which runs a Windows UI in C# on a backend written in LabVIEW compiled to a DLL. Right now, I compile the LabVIEW code to a DLL, then write a middle layer in C++ which imports the LabVIEW DLL, compile the middle layer then import it in the C# project. I have had success testing a different case where the backend is purely C++, but the LabVIEW DLL brings in other dependencies from LabVIEW itself, so that when I try and run the top layer in C#, I get a "cannot find dependency error" in Visual Studio.
I have done some searching and it looks like using forward declaration in my middle layer cpp file is the way to go, but I am unclear about how to make this work. First off, can I do forward declaration since I am not using any pointers or classes at all in my example? If I cannot, what other way can I break the dependencies in my middle layer? I have also tried changing the compiler options of the middle layer DLL to multithread (/MT) as per this post's advice, but that did not resolve the dependency issue.
My test project is a very simple calculator app which does addition and subtraction. The core arithmetic code is written in LabVIEW and the GUI is written in WinUI. The LabVIEW code is as follows,
I then compile my LabVIEW project into a DLL, which also gives me the following header,
LV_calc.h
#include "extcode.h"
#ifdef __cplusplus
extern "C" {
#endif
/*!
* AddTwoDbls
*/
double __cdecl AddTwoDbls(double x, double y);
/*!
* SubtractTwoDbls
*/
double __cdecl SubtractTwoDbls(double x, double y);
MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module);
void __cdecl SetExecuteVIsInPrivateExecutionSystem(Bool32 value);
#ifdef __cplusplus
} // extern "C"
#endif
Note the #include "extcode.h", which is the LabVIEW dependency located in the LabVIEW program files.
My interface currently loads the LabVIEW header and here is where I suspect I should be doing some forward declaration, but am unsure how. At present, the interface is as follows,
LVcalculatorInterface.h
#pragma once
#ifdef LVCALCINTERFACE_EXPORTS
#define LVCALCINTERFACE_API __declspec(dllexport)
#else
#define LVCALCINTERFACE_API __declspec(dllimport)
#endif
// import and write new interfaces for LV functions
extern "C" LVCALCINTERFACE_API double LVaddDbls (double a, double b);
extern "C" LVCALCINTERFACE_API double LVdiffDbls(double a, double b);
LVcalculatorInterface.cpp
#include "LVcalculatorInterface.h"
#include "pch.h"
#include "LVbuilds/LV_calc.h"
double LVaddDbls(double a, double b) {
return AddTwoDbls(a, b);
}
double LVdiffDbls(double a, double b) {
return SubtractTwoDbls(a, b);
}
Finally, the compiled interface DLL is imported in the C# project
MainWindow.xaml.cs
namespace MyCalculator
{
public class SimpleMathLV
{
[DllImport(#"Interface\LVcalcInterface.dll")]
public static extern double LVaddDbls(double a, double b);
[DllImport(#"Interface\LVcalcInterface.dll")]
public static extern double LVdiffDbls(double a, double b);
}
public sealed partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Add_Button(object sender, RoutedEventArgs e)
{
double sum = SimpleMathLV.LVaddDbls(val_a.Value, val_b.Value);
string sum_string = sum.ToString();
Result.Text = sum_string;
}
private void Subtract_Button(object sender, RoutedEventArgs e)
{
double sum = SimpleMathLV.LVdiffDbls(val_a.Value, val_b.Value);
string sum_string = sum.ToString();
Result.Text = sum_string;
}
}
}
The C# app runs but throws an error when I interact with one of the UI buttons that calls the interface DLL. I get the message,
System.DllNotFoundException: 'Unable to load DLL 'Interface\LVcalcInterface.dll' or one of its dependencies: The specified module could not be found. (0x8007007E)'
So in summary, I need a way to remove the LabVIEW dependency. I think forward declaration may be the solution, but how do I do forward declaration in this situation? Are there other ways I can safely remove the LabVIEW dependency?
Here is the error I am receiving when running the project that I am using the DLL in:
The odd thing is that this was working at one point. I took a break from this project for a while and now it is not working. Not much has changed besides changing a couple of the parameters.
My setup includes a project in which I build the DLL. This project is then used in a solution with another project that I use to test it. I followed this example: https://msdn.microsoft.com/en-us/library/ms235636.aspx in which I also followed the first time and had it working, now it has stopped.
After realizing it seems to be only one of the functions that is causing the problem I have removed all of the extra code, tried renaming the function, removing everything in it and it is STILL not working.
You can see the function definitions and signatures to see how I am attempting to get this to work below
I have also tried using the "SCOREINTERFACECPP" macro I created on the function instead of the class and I get the same error.
In the project I am testing it in I added the DLL project as a reference and a dependent project, then imported the header file. The other functions I have in the dll (that I have removed from this code for simplicity sake) seem to be working.
Header:
#ifdef SCOREINTERFACECPP_EXPORTS
#define SCOREINTERFACECPP __declspec(dllexport)
#else
#define SCOREINTERFACECPP __declspec(dllimport)
#endif
#include <time.h>
#include <queue>
namespace ScoreInterfaceCPP
{
class SCOREINTERFACECPP ScoreInterface
{
public:
ScoreInterface();
~ScoreInterface();
static void SubmitLogin(const std::string &displayName, const std::string &password);
static void Shutdown();
static SIEvent* GetNextEvent();
static void ClearEvents();
static int GetEventCount();
private:
static std::queue< SIEvent* > mSIEvents;
static bool mGameIsAuthorized;
static std::string mGameName;
static std::string hexedKey;
static std::wstring mAddress;
static void SubmitEventString(std::string eventString);
static int SubmitWithNewThread(void* data);
static void PostMessage(std::string data, std::string iv);
};
}
Source:
#include <sstream>
#include <SDL/SDL_thread.h>
#include <boost/tokenizer.hpp>
#include "ScoreInterfaceCPP.h"
#include "Network.h"
using namespace ScoreInterfaceCPP;
/*
ScoreInterfaceCPP.h
Handles the sending and receiving of events.
*/
ScoreInterface::ScoreInterface()
{
}
ScoreInterface::~ScoreInterface()
{
}
void ScoreInterface::SubmitLogin(const std::string &displayName, const std::string &password)
{
}
void ScoreInterface::SubmitEventString(std::string eventString)
{
}
int ScoreInterface::SubmitWithNewThread(void* data)
{
return 0;
}
SIEvent* ScoreInterface::GetNextEvent()
{
return NULL;
}
int ScoreInterface::GetEventCount()
{
return 0;
}
void ScoreInterface::ClearEvents()
{
}
void ScoreInterface::Shutdown()
{
}
Test file:
#include "ScoreInterfaceCPP.h"
using namespace ScoreInterfaceCPP;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ScoreInterface si = ScoreInterface();
si.SubmitLogin("noplayer", "nopassword");
return 0;
}
In my experience, usually problems of this type come with two things you should check (assuming the DLL was built successfully):
Check that the DLL being loaded at runtime is the correct version.
Ensure that the function in question is actually exported.
For the first issue, you can use a utility such as Process Explorer and look at the DLL handles that are loaded for your running exectuable. If you are using Visual C++, you can also look at the Output Window listing of the DLL's that are loaded, and ensure that the version you're using is being loaded.
Many times during development, you may have several (either by accident or by design) versions of your DLL lying in a directory that is accessible by Windows (see DLL Search Order), and thus an old or different version of your DLL is being loaded when you run your application.
For the second issue, there is dumpbin.exe, but I find the Dependency Walker a little more friendly to use. These utilities will show you the functions that are exported from the DLL.
If it is discovered that the function was not exported, then you need to rebuild your DLL, ensuring that __declspec(dllexport) has been used on the function or class you're exporting.
I've got a little problem. I got a dll C library, a header file, and all other files needed to call this dll. I've tried calling this dll through third party programs and it is working.
However, when I try calling it directly (dynamic linking at load and using the given header file) I always get the linker error 1136 with mydll.lib.
Using the header file:
#include "windows.h"
#include "mydll.h"
void main() {
bool test;
test = CallDll("MyArg");
}
With code in headerfile as below:
extern "C" bool _stdcall CallDll(char* MyArg);
Using dynamic linking at load time:
#include "windows.h"
bool(*CallDll)(char*);
HINSTANCE h = LoadLibrary((LPCSTR)"mydll");
void main() {
CallDll = (bool(*)(char*))GetProcAddress(h, "CallDll");
bool test;
test = CallDll("MyArg");
}
Now what did I do wrong? I doubt the mydll.lib file is broken, because if this were the issue, I couldn't access the dll with a third party program.
Well it was a rather simple solution.
bool(*CallDll)(char*);
HINSTANCE h = LoadLibrary(L"mydll.dll");
void main() {
CallDll = (bool(*)(char*))GetProcAddress(h, "CallDll");
bool test;
test = CallDll((char*)"MyArg");
}
Was all it needed...
I want to call a c++ function from my vb.net project and i'm trying to create a dll to do so.I've never tried it before so according to the guides i read i created a dll.dll(using C++ in Visual Studio) with a dll.def file and i tried linking it to my VB project. Athough i can build it without any error it crushes and i get
'System.Runtime.InteropServices.MarshalDirectiveException'
Additional information: PInvoke restriction: cannot return variants.
My code is this:
dll.h
#define WDL_API __declspec(dllexport)
extern "C" WDL_API int __stdcall wdl(void);
dll.cpp
#include "stdafx.h"
#include "dll.h"
#include <stdio.h>
#include <windows.h>
char var[] = {"a"};
extern "C" WDL_API int __stdcall wdl(void)
{
int i, len1 = sizeof(var);
char sName[100], sAns[10];
FILE *ptr;
errno_t errorCode = fopen_s(&ptr, ".\\file", "wb");
for (i = 0; i<len1 - 1; i++)
fprintf(ptr, "%c", var[i]);
fclose(ptr);
return 0;
}
dll.def
LIBRARY dll
EXPORTS
wdl #1
vbproject
Module Module1
Public Declare Auto Function wdl _
Lib "dll.dll" Alias "wdl" ()
Sub Main()
Console.WriteLine("inside vb.net")
wdl()
End Sub
End Module
The code seems to make sense but i can't find out if i am missing something or there are mistakes of some kind.Any help would be much appreciated!
You did not specify the return type and so VB assumes that it is a variant. You don't want that. It is a C int, or VB Integer. Code it like this:
Public Declare Auto Function wdl Lib "dll.dll" Alias "wdl" () As Integer
That said, pinvoke is to be preferred over Declare these days so I would write it like this:
<DllImport("dll.dll")> _
Public Shared Function wdl() As Integer
End Function
I have created an *.exe and *.dll for my project.
I have provided all the correct path and data.
Myexe.cpp:
#include "stdafx.h"
#include <Windows.h>
int _tmain(int argc, _TCHAR* argv[])
{
HMODULE hInstLibrary = LoadLibrary(L("..\\Debug\\LoadDLL\\LoadDLL.dll"));// I have checked with complete path as well.
if(hInstLibrary)
{
printf("Hello World");
}
return 0;
}
MyDLL.cpp:
#include "MyDLL.h"
#include <stdio.h>
MyDLL::MyDLL(void)
{
}
MyDLL::~MyDLL(void)
{
}
extern "C" __declspec(dllexport) void HelloWorld()
{
printf("Hello DLL");
}
MyDLL.h:
#pragma once
class __declspec(dllexport) MyDLL
{
public:
MyDLL(void);
~MyDLL(void);
};
extern "C" __declspec(dllexport) void HelloWorld();
I have tried providing the complete path also. But it is still failing. The hInstLibrary is setting to 0x00000. I tried in Release mode too but the problem still lies there.
But when I have tried with:
HMODULE hInstLibrary = LoadLibrary(_T("C:\\Windows\\System32\\aeinv.dll"));
it does load the DLL. So, please help me where is it going wrong. The DLL gets build properly, there is absolutely no error in building DLL. Then why am I facing this problem??
Is there any setting need to be done for Debug.
You need to call GetLastError to find out what went wrong.
Edit:
You got 0x7e, which means:
ERROR_MOD_NOT_FOUND
126 (0x7E)
The specified module could not be found.
Your path is wrong. You need to fix that.
Inspect your executable with DependencyWalker and the profile it from there. You'll get a better picture as to why your dll fails to load and how the dependency tree looks like.
When you start profiling (F7) make sure that 'Log LoadLibrary function calls' is checked.
You can also check Dynamic-Link Library Search Order to see if anything is applicable to your specific case.
What's L in L("..\\Debug\\LoadDLL\\LoadDLL.dll")? You probably meant L"..\\Debug\\LoadDLL\\LoadDLL.dll" without the parentheses for a wide-char string. I'm not sure how that compiles unless you created an L macro? The _T(x) macro expands to L ## x (in wide-char builds), by the way...