Having trouble with plugins.

Ok, I am relatively new to C++, but not to General OOP, so I thought this would be a more appropriate place to post. First off, heres the sources:
Pluginable app: http://entityreborn.co.cc/PluginSDK.zip
Plugin: http://entityreborn.co.cc/add.zip

The idea is to load a plugin that uses a well known interface (by passing a string for the DLL/SO's name), and call a method of that class. Unfortunately, it aint working for me. Heck, I'll post most of the code here for those that want it...

main program file:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include "os_call.h"
#include <iostream>
#include <exception>
#include "Intrface.h"

using namespace std;

int main(int argc, char* argv[])
{
	Intrface *PlugObject;
	void *hDLL;
	cout << "Attempting to load library 'add'\n";
	hDLL = LoadSharedLibrary("add");

	if(hDLL)
	{
	    cout << "Attempting object retrieval\n";
            PlugObject = (Intrface*)GetFunction(hDLL,"GetPluginObject");
            if(PlugObject){
                cout << "Attempting 'add' call\n";
                int iTmp = PlugObject->Add(8,5);
                cout << "8 + 5 = " << iTmp;
            }
            else
            {
                cout << "Bad implementation\n";
            }
            FreeSharedLibrary(hDLL);
        }
	else
	{
	    cout << "Could not find library\n";
		return 1;
	}
	return 0;
}


interface:
1
2
3
4
class Intrface {
    public:
        virtual int Add (int, int)=0;
};


plugin .cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "add.h"

#ifdef _WIN32
	bool APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
				 )
#else
	 bool DllMain( void * hModule,
                       unsigned long  ul_reason_for_call,
                       void *lpReserved
				 )
#endif
{
    switch (ul_reason_for_call)
	{
		case 1://DLL_PROCESS_ATTACH:
            return true;
		case 2://DLL_THREAD_ATTACH:
            break;
		case 3://DLL_THREAD_DETACH:
            break;
		case 0://DLL_PROCESS_DETACH:
			break;
    }
    return true;
}

extern "C" ADD_API Intrface* GetPluginObject()
{
    PluginObject = new CAdd;
    return PluginObject;
}

extern "C" int CAdd::Add(int a, int b)
{
    return (a + b);
}


plugin header:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#ifdef _WIN32
    #include <windows.h>
    #define ADD_API __declspec(dllexport)
#else
	#include "dlfcn.h"
	#define ADD_API
#endif

#include "Intrface.h"
class CAdd : public Intrface {
    public:
        int Add(int, int);
};

CAdd* PluginObject;


os_call.h is not relavent here, but download the PluginSDK.zip mentioned above to see it.

Both the plugin project and the app project have their own copy of the interface class, so that may be a problem, I dunno. Basically the problem is when PlugObject->Add(x,x); is called, my app segfaults. any ideas?
Last edited on
You might want to post this question in the Windows forum, though a lot of responders check all the forums anyway.

Gotcha. Its aimed at multi platformness, but will do.
You must have something wrong in your wrapper functions in os_call. This is a minimal WIN32 implementation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <windows.h>
#include <iostream>

class IAdd
{
public:
	virtual int Add(int, int) = 0;
};

typedef IAdd* FuncCreate(const char*);
typedef void  FuncDestroy(IAdd*);

int main(int argc, char* argv[])
{
	if (HINSTANCE h = LoadLibrary("Add.dll"))
	{
		FuncCreate*  Create  = (FuncCreate*)GetProcAddress(h, "Create");
		FuncDestroy* Destroy = (FuncDestroy*)GetProcAddress(h, "Destroy");
		if (Create && Destroy)
		{
			if (IAdd* pAdd = Create("CAdd"))
			{
				std::cout << pAdd->Add(8, 11) << std::endl;

				Destroy(pAdd);
			}
		}

		FreeLibrary(h);
	}

	return 0;
}


This must build to Add.dll
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <windows.h>
#include <string.h>

class IAdd
{
public:
	virtual int Add(int, int) = 0;
};

class CAdd : public IAdd
{
public:
	virtual int Add(int a, int b) { return a + b; }
};

extern "C" __declspec(dllexport) IAdd* Create(const char *arg)
{
	if (strcmp(arg, "CAdd") == 0)
		return new CAdd;

	return 0;
}

extern "C" __declspec(dllexport) void Destory(IAdd* p)
{
	delete p;
}


For Unix, replace LoadLibrary with dlopen, GetProcAddress with dlsym, FreeLibrary with dlclose, Add.dll with libadd.so, and remove the declspec mumbo jumbo.
Ok, thanks, I will give that a try. I have one problem with your implementation though... In your Create(); you use a char pointer to define the actual plugin. That's all fine and all, but in the final usage of this system, the app will have no clue as to what the plugin's name will be. I intend this to be a program that scans a directory and loads any plugins it finds, discarding the ones that aren't compatible. The only thing the app will know is the interface, and how to use that interface. I'll implement your version, and see what happens, thanks!

EDIT: Unfortunately, either I am doing something wrong, or you did. Heres my code for the app:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <windows.h>
#include <iostream>

class IAdd
{
public:
	virtual int Add(int, int) = 0;
};

typedef IAdd* FuncCreate(const char*);
typedef void  FuncDestroy(IAdd*);

int main(int argc, char* argv[])
{
    HINSTANCE h = LoadLibrary("add.dll");
	if (h)
	{
		FuncCreate*  Create  = (FuncCreate*)GetProcAddress(h, "Create");
		FuncDestroy* Destroy = (FuncDestroy*)GetProcAddress(h, "Destroy");
		if (Create)
		{
		    if (Destroy)
            {
                if (IAdd* pAdd = Create("CAdd"))
                {
                    std::cout << pAdd->Add(8, 11) << std::endl;

                    Destroy(pAdd);
                }
                else
                {
                    std::cout << "Could not create object" << std::endl;
                }
            }
            else
            {
                std::cout << "Bad implementation: Destroy" << std::endl;
            }
		}
		else
        {
            std::cout << "Bad implementation: Create" << std::endl;
        }

		FreeLibrary(h);
	}
	else
	{
	    std::cout << "Could not load library" << std::endl;
	}

	return 0;
}


The DLL is exactly what you have posted above.
Basically, I get "Bad implementation: Destroy" when I run the program. I inserted the comments when I saw that nothing was spat out on the console. I'll mess around and see what happens.

EDIT EDIT: I figured it out: You posted a spelling mistake in the Add.dll class. You entered Destory instead of Destroy :)
Last edited on
Topic archived. No new replies allowed.