Hi guys, I want to build a DLL to access classes and functions from a Visual Basic program
This right here is my class

class SimpleDevice : public IHaptikDevice
{
   private:
// Callback Related
   PVOID object;
   PVOID method;
   UINT32 timerId;

// State
   HaptikData data;
   HaptikUserData userdata;
   
   public:
   static Vector3 startPosition;
   static bool buttonPressed;
   
// IHaptik interface
   public:
   UINT32 Init(PVOID inMethod,PVOID inObject);
   UINT32 Start();
   UINT32 Stop();
   UINT32 Release();
   UINT32 Read(HaptikData& data);
   UINT32 Write(HaptikData& data);
   UINT32 SetRate(FLT32 rateInHz);
   FLT32 GetRate();
   UINT32 GetInfo(HaptikDeviceInfo& info);
   UINT32 SetUserData(DWORD userData);
   DWORD GetUserData();
   UINT32 SetCallback(PVOID method = NULL,PVOID object = NULL, DWORD reserved = NULL);
   UINT32 GetCallback(PVOID& method,PVOID& object = NULL_REFERENCE(PVOID),DWORD reserved = NULL);
   UINT32 GetLastError();
   UINT32 GetCalibrationStatus();
   UINT32 Recalibrate(UINT32 reserved = NULL);
   
   public:
   VOID Callback();
   
   public:
   SimpleDevice();
   ~SimpleDevice();
};

After making a New Project Windows Application DLL Export Library I started making my export classes (there are two, which access a special header from Haptik Library to control my Novint falcon)

So I did this

#ifdef FALCON_PLUGIN_EXPORTS
	#define FALCON_PLUGIN_API __declspec(dllexport)
#else
	#define FALCON_PLUGIN_API __declspec(dllimport)
	#pragma message("Automatic Link to Falcon_Plugin.lib")
	#pragma comment(lib, "Falcon_Plugin.lib")
#endif
////////////////////
//       List of  #Includes
/////////////////////

class FALCON_PLUGIN_API SimpleDevice : public IHaptikDevice
{
   private:
// Callback Related
   PVOID object;
   PVOID method;
   UINT32 timerId;

// State
   HaptikData data;
   HaptikUserData userdata;
   
   public:
   static Vector3 startPosition;
   static bool buttonPressed;
   
// IHaptik interface
   public:
   UINT32 Init(PVOID inMethod,PVOID inObject);
   UINT32 Start();
   UINT32 Stop();
   UINT32 Release();
   UINT32 Read(HaptikData& data);
   UINT32 Write(HaptikData& data);
   UINT32 SetRate(FLT32 rateInHz);
   FLT32 GetRate();
   UINT32 GetInfo(HaptikDeviceInfo& info);
   UINT32 SetUserData(DWORD userData);
   DWORD GetUserData();
   UINT32 SetCallback(PVOID method = NULL,PVOID object = NULL, DWORD reserved = NULL);
   UINT32 GetCallback(PVOID& method,PVOID& object = NULL_REFERENCE(PVOID),DWORD reserved = NULL);
   UINT32 GetLastError();
   UINT32 GetCalibrationStatus();
   UINT32 Recalibrate(UINT32 reserved = NULL);
   
   public:
   VOID Callback();
   
   public:
   SimpleDevice();
   ~SimpleDevice();
};

Am i on the right direction? Also when I'm declaring the functions I do:

[I]type[/I] SimpleDevice::[I]Function_Name[/I]<[I]body[/I]>

Recommended Answers

All 5 Replies

It seems alright to me as far as the procedure you have taken to export the class from the DLL. That is the way to do it, as far as I know, but I don't do it often because of the remarks that follow.

One important thing that always needs to be mentioned when talking about exporting C++ classes from DLLs is that you have to make sure that all the code that uses this DLL is also compiled with the exact same compiler (same version (major, minor and revision), same OS, same platform (32bit or 64bit)). So, that is very restrictive and often makes the whole idea of using DLL to export classes very impractical. This link provides you a simple explanation of the problem. Basically, the options to cope with this problems are to either:
- export only C functions from DLLs (no class methods nor objects as parameters).
- use a ready-made ABI like COM, ActiveX, or whatever (this will basically confine you to Windows, I don't know of any major ABI that is cross-platform).
- follow very strict rules in your programming style to ensure binary compatibility (which is not a trivial task, relies heavily on the PImpl idiom (Cheshire Cat or Compiler Firewall)).
- stick to one single compiler and OS, and recompile your DLLs for every distribution or new minor version of all compilers (very hard to maintain if you expect wide distribution over some period of time).

commented: Again... priceless help :D +1

Thanks Mike, I'm still working on it.

And yes I understand your concern on the portability. This is a school project, I am programming a Novint Falcon to handle a CRS F3 Robot.
The CRS F3 robot library are built for Visual Basic, and it's a HUGE library, so I made my main interface in Visual Basic (plus I'm a noob programmer)

So I had my Novint Falcon C++ program thrown to the garbage in the process (I had the interface in Visual C++) but making a DLL exportable and interfaceable with Visual Basic has a lot more info on the web than porting the CRS F3 basic libraries to C++.

I have one day to get this done, so wish me luck, fortunately the robot is already programmed and the algorithms are implemented, so we are good :D :D

I'll keep you posted

I have a question Mike, normally the only thing I export to make a DLL (according to the manual) is this:

extern "C" __declspec(dllexport) PVOID GetInterface(UINT32 interfaceId)
{
   if (interfaceId == HAPTIK_IHAPTIKPLUGIN) return &plugin;
   else return NULL;
}

But for using my DLL to be interfaceable with Visual Basic I am exporting the classes AND the function GetInterface

In the Library's manual it says that this function is the entry procedure that the library uses to request an interface with the falcon.

What do you think?

Well there has to be other functions to export also. Basically, if the code that uses the DLL is in Visual Basic, then essentially, you are entirely restricted to a C interface (no class exports). Assuming "plugin" in an object of some class, then the VB code has absolutely no way to deal with that pointer directly. Normally, these things are handled by sending the pointer "plugin" with the GetInterface function (or anything similar to that) which is assumed to be an opaque handle that gets sent to any other functions exported by your DLL that take this handle as the first argument (this is typical of any API like win32 or posix or anything else). It could go something like this:

typedef void* HANDLE;

extern "C" __declspec(dllexport) HANDLE GetInterface(UINT32 interfaceId)
{
   if (interfaceId == HAPTIK_IHAPTIKPLUGIN) return new HaptikPlugin();
   else return NULL;
};

extern "C" __declspec(dllexport) void StartInterface(HANDLE interface)
{
  if(interface)
    reinterpret_cast<HaptikPlugin*>(interface)->start();
};

You should look into your documentation if it doesn't require a certain set of standard functions to be exported from the DLL that actually can be used to use whatever plugin or interface you are exporting. I'm sure they have a set of specific functions for every type of interface you want to export (and this GetInterface is probably just a common function to get a handle to any one of the interfaces.. this is at least what I would have done if I were them). Basically, exporting a class via a C interface involves writing a trivial function like that "StartInterface" function above for every method of your class (basically, casting and then forwarding the function call).

I keep reading and re reading what you wrote.
So no classes, got that part.
To export a method inside a class I create a handle of the class and the use the handle to access the method inside of it???

I have not found any information regarding that on the web

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.