I made a DLL in VC++ using Visual Studio 2008 professional and I'm trying to test(debug) it!
So I made another project but when I try to make a step into a class I made it just steps forward.
I also try click on the class and go to the definition (where it appear Cannot Load Symbol)
I try in tool>>options>>Debuging>>symbols to add the path to the .pdb file
My code as the dll declaration
#pragma once
__declspec(dllexport) long sdk_init();
//__declspec(dllexport) long sdk_release();
__declspec(dllexport) long sdk_connect(long handle);
__declspec(dllexport) long sdk_getObjectList(long handle);
//__declspec(dllexport) long sdk_disconnect(long handle);
__declspec(dllexport) long sdk_playStream(long handle, int idx);
__declspec(dllexport) long sdk_stopStream(long handle, int idx);
and then the implemantetion for instance ~
long sdk_init(){
CDataManager* m_DataManager = new CDataManager();
int i = m_DataManager->InitXns();
if(i == 0){
return 0;
}
return (long) m_DataManager;
}
The class I can't step into is the CDataManager, that is a class created by me.
#include
using namespace std;
#include <list>
class CDataManager :
public IDeviceSink,
public IMediaSink
{
public:
int InitXns(void);
int Connect(int nDeviceId);
int GetObjectList(void);
int RequestLiveStream(int videoSource);
int StopLiveStream(int videoSource);
private:
int m_bInitXns;
int login;
//store in list?
XNS_DEVICE2 m_sDevice;
//safe store?
XNS_OBJECT *m_pObject;
XNS_OBJECT *m_pVideoSource;
public:
CDataManager();
virtual ~CDataManager();
int SetWnd(HWND hWnd);
long OnResponse(XNS_REQUEST* pReq);
long OnEvent(XNS_EVENT* pEvent);
long OnVideo(UINT nMID, XNS_VIDEO_HEADER* pVideo);
long OnAudio(UINT nMID, XNS_AUDIO_HEADER* pAudio);
I managed to fix my problem:
I changed the "Debugger Type" to "Mixed" in configuration properties>>debugging of my test solution
Anyhow, I don't understand the why I need to do that, if someone was an explanation please post.
Related
I'm very new to writing c++ plugins for unity but must do so now. I have been loosely following this tutorial and created the following in a visual studio dll project uncreatively called UnityPluginTest:
#include <stdint.h>
#include <stdlib.h>
#include <time.h>
#define DLLExport __declspec (dllexport)
extern "C"
{
DLLExport int RandomNumber(int min, int max)
{
srand((unsigned int)time(0));
return (rand() % (max - min) + min);
}
}
I created a completely new unity project to test it (Unity 2020.2.f1 if it matters), and copied the compiled .dll file into a new folder Assets/Plugins. I then made a new script called (equally uncreatively) TestFirstUnityPluginTest.cs which contains the following:
using System.Runtime.InteropServices;
using UnityEngine;
public class TestFirstUnityPluginTest : MonoBehaviour
{
const string dll = "__Internal";
[DllImport(dll)]
private static extern int RandomNumber(int min, int max);
void Start()
{
Debug.Log(RandomNumber(0, 10));
}
}
When I put the script on a gameobject and hit play, I get an error stating "EntryPointNotFoundException: RandomNumber" with a stack trace pointing to the Debug.Log() call. Any ideas what I might be doing wrong? Thank you in advance.
You should specify entry point and use DECORATED name:
replace [DllImport(dll)] by [DllImport("YOUR_DLL_NAME.dll", EntryPoint = "DecoratedFunctionName")]
My C++ code:
__declspec(dllexport) int Double(int number)
{
return number * 2;
}
My Unity3d C# code:
[DllImport("Dll4_CPP.dll", EntryPoint = "?Double##YAHH#Z")]
public static extern int Double(int number);
void Start()
{
Debug.Log(Double(10));
}
Decorated name - name of the function inside DLL (compiler renames it).
Dumpbin.exe helps to find it:
VisualStudion2019 -> Tools -> CommandLine -> DeveloperComandPrompt
cd <your PathToDLL>
dumpbin /exports Dll4_CPP.dll
it will print:
...
1 0 00011217 ?Double##YAHH#Z = #ILT+530(?Double##YAHH#Z)
...
Source
I am a beginner, and I just built a project including a dll in c++. The project is made up with 2 sub projects:
A static Library project containing the files:
Rational.h
#pragma once
class Rational
{
private:
int num;
int den;
public:
Rational(int num_, int den_);
Rational();
double getValue();
};
Rational.cpp
#include "Rational.h"
Rational::Rational()
{
}
Rational::Rational(int num_, int den_) : den(den_), num(num_)
{
}
double Rational::getValue()
{
return (double)num / (double) den;
}
A dll project containing the files:
Proxy.h
#pragma once
#define DLL_EXPORT __declspec(dllexport)
extern "C"
{
DLL_EXPORT double __stdcall getRationalValue(int num_, int den_);
}
Proxy.cpp
#include "Proxy.h"
#include "Rational.h"
DLL_EXPORT double __stdcall getRationalValue(int num_, int den_)
{
Rational fraction(num_, den_);
return fraction.getValue();
}
The dll function is used in an Excel file. Here is the declaration of the function to be used:
Declare PtrSafe Function getRationalValue_vba Lib "C:\...\Documents\Visual Studio 2013\Projects\Rational\x64\Debug\RationalDll.dll" Alias "getRationalValue" (ByVal num As Long, ByVal den As Long) As Double
In order to test this function I have the following sub in vba:
Sub test()
shtTests.Cells(1, 1) = getRationalValue_vba(4, 5)
End Sub
It seems to work fine.
The problem occurs when I want to launch the debugger from Visual Studio.
In visual studio project:
Properties>Debugging>Command was set to Excel.exe localisation.
I set a break point at the "return" line of proxy.cpp file.
When I launch the debugger, excel opens well. But then, when I execute sub test(), the break point in visual is never reached, and the application crashes.
Can you help me understand this issue?
I work with an application that appears (just started a few weeks ago, so I am still learning the older apps) to be built in C and my company wants to use that program's ability to make a call to an outside DLL to extend some new functionality. To do this, I started working on my POC, which is the first two files below. The only specification we were given was that the dll has to export the following function:
extern int __stdcall TestMethod_LoadCustomer(const char * name, char * id);
I tried to implement that as follows:
TestDLL.h
#define TestDLL_API __declspec(dllexport)
namespace TestDLL
{
class TestDLL
{
public:
static TestDLL_API int TestMethod_LoadCustomer(const char* name, char* id);
};
}
TestDLL.cpp
// TestDLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "TestDLL.h"
#include <string.h>
extern "C" int __declspec(dllexport) __stdcall TestMethod_LoadCustomer(const char* name, char* id)
{
if (strlen(name) <= 8) {
strcpy(id, name); // name contains customer id
} else {
id[0] = 0; // Customer not found
}
return 0;
}
These two files compile fine. The problem comes in when I try to test this dll via a separate little console app shown here:
RunTEST.cpp
// RunTest.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include "TestDLL.h"
using namespace std;
int _tmain()
{
char* id= "";
TestDLL::TestDLL::TestMethod_LoadCustomer("77777", id);
cout << id;
cin >> id;
return 0;
}
All I am looking for is to be able to pass in a character string into the call TestMethod_LoadCustomer() and have it be added to the id field.
When I actually try to build this solution, I get the following error:
"error LNK2019: unresolved external symbol "public: static int __cdecl TestDLL::TestDLL::TestMethod_LoadCustomer(char const *, char *)" (?TestMethod_LoadCustomer#TestDLL#1#SAHPBDAD#Z) referenced in function _wmain"
I am assuming it has something to do with the way I am trying to reference it in my client app, but I am not sure. I have looked at other LNK2019 errors on StackOverflow, but none of those solutions seemed to work here, of I have incorrectly implemented them. Can any one assist in helping me get rid of this error message?
On the TestDLL.cpp file is missing two things:
1) The namespace TestDLL.
2) the TestDLL:: before the method name.
// TestDLL.cpp : Defines the exported functions for the DLL application.
//
#include "stdafx.h"
#include "TestDLL.h"
#include <string.h>
namespace TestDLL {
extern "C" int __declspec(dllexport) __stdcall TestDLL::TestMethod_LoadCustomer(const char* name, char* id)
{
if (strlen(name) <= 8) {
strcpy(id, name); // name contains customer id
} else {
id[0] = 0; // Customer not found
}
return 0;
}
}
While defining the function in TestDLL.cpp you didn't mention that the function is member of the class TestDLL.
I have a few questions about DLL's. I tried a lot but I can not get the complete picture. Most examples are in C# etc.
With the wizard in VS2005 I created a unmanaged MFC regular DLL (must be MFC because of remaining code). Then I tried to import it in a VS2005 managed .NET C++ application. See code below.
mfc_main.h:
//---------------------------------------------------------
// mfc_main.h : main header file for the mfc_main DLL
//---------------------------------------------------------
#pragma once
#ifndef __AFXWIN_H__
#error "include 'stdafx.h' before including this file for PCH"
#endif
#include "resource.h" // main symbols
class __declspec(dllexport) Cmfc_mainApp : public CWinApp
{
public:
Cmfc_mainApp();
// Overrides
public:
virtual BOOL InitInstance();
int SayHello(int j);
int init;
DECLARE_MESSAGE_MAP()
};
mfc_main.cpp:
//----------------------------------------------------------------
// mfc_main.cpp : Defines the initialization routines for the DLL.
//----------------------------------------------------------------
#include "stdafx.h"
#include "mfc_main.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
BEGIN_MESSAGE_MAP(Cmfc_mainApp, CWinApp)
END_MESSAGE_MAP()
Cmfc_mainApp::Cmfc_mainApp()
{
}
Cmfc_mainApp theApp;
BOOL Cmfc_mainApp::InitInstance()
{
CWinApp::InitInstance();
return TRUE;
}
int Cmfc_mainApp::SayHello(int j)
{
init = 12; // Comment this out the application works !!!!
return j * 6;
};
in application
[DllImport("mfc_main.dll",
EntryPoint = "?SayHello#Cmfc_mainApp##QAEHH#Z",
ExactSpelling = true)]
static int SayHello(int a);
......
private: System::Void button_Click(System::Object^ sender, System::EventArgs^ e)
{
int retval = SayHello(2);
}
My questions are:
1 - Why is it working without the init = 12 in the function SayHello and with the application crashes (error: Attempted to read or write protected memory)?
2 - Is in this case the InitInstance() executed although I don't call it (and why is there no ExitInstance)?
3 - Why do I see some examples giving the EntryPoint when using DLLImport and some don't?
4 - Can I give a delegate as parameter to a function in a MFC C++ DLL instead of a normal function pointer, to create a callback?
Methods cannot be P/Invoked. If you want to export a class from unmanaged DLL to be used in managed world, you have to flatten it, eg.
Create a constructor function, which looks like:
__declspec(dllexport) void * __stdcall MyClass_Create()
{
return new MyClass();
}
Create a destructor function, which looks like:
__declspec(dllexport) void * __stdcall MyClass_Destroy(MyClass * instance)
{
delete instance;
}
Flatten method calls. Let's suppose, that you have the following method in your class:
int MyClass::MyMethod(int i, double j) { ... }
Then you have to create a following function:
__declspec(dllexport) int __stdcall MyClass_MyMethod(MyClass * instance, int i, double j)
{
return instance->MyMethod(i, j);
}
Prepare P/Invoked external methods in C# (You already know how to do it, so I'll omit these)
Create instance of your class:
IntPtr instance = MyClass_Create();
Then call its method:
int i = MyClass_MyMethod(instance, 4, 2.0);
Finally, destroy the class:
MyClass_Destroy(instance);
Don't forget to add some error checking - I omitted it to keep the example clear.
I have a new problem with my C++ DLL... I have tried exporting the entire class instead of only one method. But the program doesn't want to compile now because of that the global scope has no GetUrl
Here is my "UrlConnector.h":
#define ConnectMe __declspec( dllexport )
namespace ConnectHttps
{
class ConnectMe
{
void GetUrl(char *url, unsigned int bufferLength);
};
}
and here is the part of my UrlConnector.cpp that isn't compiling:
#include "UrlConnector.h"
#include "MyConnectionClass.h"
#include
using namespace std;
namespace ConnectHttps
{
void ConnectMe::GetUrl(char* url, unsigned bufferLength)
{
MyConnectionClass initSec;
string response = initSec.GetResult();
strncpy_s(url, bufferLength, response.c_str(), response.length());
}
}
Now, I would like to be able to create an DLL from this, and I would like to make a test program to call the class and the method GetUrl from a dll. I'm using Visual Studio 2010 with Visual C++ DLL.
I've also managed to read this from the MSDN and this tutorial as well, but I just can't seem to get it to work!
I would really appreciate any help!
Unless I'm mistaken, you don't seem to be giving your class a name.
You made ConnectMe not a class name but a macro to export your class, but your class should have a name
Maybe try
#define EXPORT_IT __declspec( dllexport )
namespace ConnectHttps
{
class EXPORT_IT ConnectMe
{
void GetUrl(char *url, unsigned int bufferLength);
};
}
Also I'm not 100% sure of this because I don't have access to a compiler at the moment, but typing:
namespace ConnectHttps {
...
}
In your .cpp file isn't correct. Instead you should have:
void ConnectHttps::ConnectMe::GetUrl(char* url, unsigned bufferLength)
{
MyConnectionClass initSec;
string response = initSec.GetResult();
strncpy_s(url, bufferLength, response.c_str(), response.length());
}