Sign in to follow this  
hymerman

Unity Need help getting classloader to work across DLL boundary

Recommended Posts

Hi again, folks, Sorry for the long post, but I'm in need of a bit of help, so I'd really appreciate it if you'd read it. I need a classloader for my project, since it fits the plugin architecture perfectly and will (hopefully) simplify our current method of loading plugins. I'm basing my code pretty much exclusively on the s11n classloader, specifically the version presented in this paper: http://s11n.net/papers/classloading_cpp.html I've taken that code, rearranged it a little, refactored slightly, but it is still functionally equivalent - the one thing I have changed is the static object factory map, from a reference to a pointer, since it wouldn't compile otherwise. Now, I hate people that post all their code up and expect others to read through it all, but I'm really in desperate need here, and I promise it'll only happen this once! My exact code is shown below: ObjectFactory.h
#ifndef OBJECTFACTORY_H
#define OBJECTFACTORY_H

template <typename BaseT, typename SubT = BaseT> // SubT must be-a BaseT.
struct ObjectFactory {
	typedef BaseT resultType;
	typedef SubT actualType;

	static resultType* newInstance() { return new actualType; }
	static resultType* noInstance() { return 0; }
};

#endif

Instantiator.h
#ifndef INSTANTIATOR_H
#define INSTANTIATOR_H

#include <map>

template<typename BaseType, typename KeyType = std::string>
class Instantiator {
public:
	typedef BaseType valueType;
	typedef KeyType keyType;
	typedef valueType *( *factoryType )();
	typedef std::map<keyType, factoryType> objectFactoryMap;

	static valueType* instantiate(const keyType & key) {
		typename objectFactoryMap::const_iterator it = getFactoryMap()->find( key );

		if (it != getFactoryMap()->end())
			return (it->second)();

		return 0;
	}

	static void registerFactory( const keyType & key, factoryType fp = 0 ) {
		if( ! fp ) fp = ObjectFactory<valueType>::noInstance;
		getFactoryMap()->insert( objectFactoryMap::value_type( key, fp ) );
	}

	template <typename SubOfBaseType>
	static void registerSubtype( const keyType & key, factoryType fp = 0 ) {
		if( ! fp ) fp = ObjectFactory<valueType,SubOfBaseType>::newInstance;
		registerFactory( key, fp );
	}

	static objectFactoryMap * getFactoryMap() {
		static objectFactoryMap* meyers = new objectFactoryMap;
		return meyers;
	}

	static bool isRegistered( const keyType & key ) {
		return getFactoryMap()->end() != getFactoryMap()->find( key );
	}
};

#endif

Register.h
#ifndef ST_TYPE
#error "You must define ST_TYPE before including this file."
#endif

#ifndef ST_TYPE_NAME
#error "You must define ST_TYPE_NAME before including this file."
#endif

#ifndef ST_BASE_TYPE
#define ST_BASE_TYPE ST_TYPE
#endif

#include "Instantiator.h"
#include "ObjectFactory.h"

// Anonymous namespace for linking reasons
namespace {
	#ifndef ST_REG_CONTEXT
	#define ST_REG_CONTEXT
		// A unique (per Context/per compilation unit) space to assign
		// a bogus value for classloader registration purposes.
		// Included once per compilation unit
		template <typename Context>
		struct stereoshift_reg_context {
			static bool placeholder;
		};

		template<typename Context> bool stereoshift_reg_context<Context>::placeholder = false;
	#endif // ST_REG_CONTEXT

	// Register a factory with the classloader during static initialization
	// Use static dummy variable assigned using comma operator (very cheeky trick)
	bool stereoshift_reg_context< ST_TYPE >::placeholder = (
	#ifdef ST_ABSTRACT_BASE
		// register a no-op factory if registering an abstract class:
		Instantiator<ST_TYPE>::registerFactory(
			ST_TYPE_NAME,
			ObjectFactory< ST_TYPE >::noInstance ),
	#else
		// register the default factory if not abstract:
		Instantiator<ST_BASE_TYPE>::registerSubtype<ST_TYPE>(ST_TYPE_NAME),
	#endif // ST_ABSTRACT_BASE
		true);
}

// Undef everything so header can be included again
#undef ST_TYPE
#undef ST_BASE_TYPE
#undef ST_TYPE_NAME
#ifdef ST_ABSTRACT_BASE
# undef ST_ABSTRACT_BASE
#endif

... And to show you how this would all be used, here is an example pair of classes: ExampleClass.h
#ifndef EXAMPLECLASS_H
#define EXAMPLECLASS_H

#include <iostream>

class ExampleClass {
public:
	ExampleClass() { std::cout << "base constructing" << std::endl; }
	virtual ~ExampleClass() { std::cout << "base destructing" << std::endl; }

	virtual void run() = 0;
};

#define ST_TYPE ExampleClass		// the type we want to register
#define ST_TYPE_NAME "ExampleClass"	// the name of the type (need not be the same as the type)
#define ST_ABSTRACT_BASE 1
#include "Register.h"				// include the supermacro

#endif

ExampleSubclass.h
#ifndef EXAMPLESUBCLASS_H
#define EXAMPLESUBCLASS_H

#include <iostream>
#include "ExampleClass.h"

class ExampleSubclass : public ExampleClass {
public:
	ExampleSubclass() { std::cout << "subclass constructing" << std::endl; }
	virtual ~ExampleSubclass() { std::cout << "subclass destructing" << std::endl; }

	virtual void run() { std::cout << "subclass running" << std::endl; }
};

#define ST_TYPE ExampleSubclass			// the type we want to register
#define ST_BASE_TYPE ExampleClass		// the base type of the type we want to register
#define ST_TYPE_NAME "ExampleSubclass"	// the name of the type (need not be the same as the type)
#include "Register.h"					// include the supermacro

#endif

Now, this all works fine when in my lovely little test project, when things aren't in DLLs. Everything gets registered statically, and available for instantiation through Instantiator<Base>::instantiate("Name");. But when I put into my actual project, and try to register things in DLLs, things go a bit awry. When I run the debugger on the app, I see that as soon as the DLL is loaded (through whatever means), the register functions are called, which is great, but later on the information is not stored in the static object factory map so all instantiations fail. Now, I'm quite certain this is due to the function:
static objectFactoryMap * getFactoryMap() {
	static objectFactoryMap* meyers = new objectFactoryMap;
	return meyers;
}
Could it be that I changed the objectFactoryMap to a pointer rather than a reference? I know there are issues with using 'static' things across DLL boundaries, but I'm hoping somebody could point out what my particular problem is! So please, if you can, tell me what's wrong with my code, I'm getting desperate now! Thanks in advance, and than you for being such an awesome community!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
i think you don't want to recustruct your static map on every call to getFactoryMap(). Check if the pointer already is valid first.

static map_type * the_map = 0;
static map_type *get_map()
{ if(!the_map) the_map = new map_type; return the_map; }

Share this post


Link to post
Share on other sites
Thanks, that helped (well spotted), but the problem is still there. It seems it's more fundamental, as I've noticed in my other thread. I need to separate out the implementation and definition of some of the methods to avoid the code being compiled into both app and DLL, but the restraint of having to keep these in the same file due to the templated classes prevents me from doing this. Looks like I'm going to have to use an inferior solution!

Unless anyone can suggest a way round this, of course....

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Partner Spotlight

  • Forum Statistics

    • Total Topics
      627665
    • Total Posts
      2978524
  • Similar Content

    • By Kurupted Playz
      Hey, I'm looking for some people that can help me with a game that I'm making that is a 3d platformer.
      I mostly need someone for character design and animation,  I can do some coding but if you can do coding as well you're still welcome because I'm still not the greatest at coding just yet.
      if you need to contact me add me on discord @ Kurupted#1206
       
    • By Jcyshadow97
      Hi,guys.I m working on a Fantasy RPG.Currently i m work alone on the project.I really need someone can make UI stuff.If someone can handle it please feel free to contact me on email: 270514974@libero.it.
      Thank you guys and sorry for my english.
       
       



    • By STRATUM the Game
      Hey, everyone! This is my first post here.
      I would like to know what you think about my project called STRATUM. It's a 2D platformer that is heavily based on storytelling and boss fighting while trekking through the world.

      Everything in STRATUM takes place in the first century AD, in a world that wraps our own universe, called  The Stratum. A parallel Universe that is the home of the Christian deities . In this game you will play as a Dacian warrior, unfamiliar with everything in this world, you’ll get to know and understand The Stratum together with him.
      The main thing that I want with STRATUM is to reinvent the known lore and history of the Christian deities and realms. 
      The story is unconventional, it plays down a lot of the mysticism of Hell or Heaven and it gives it a more rational view while keeping the fantastic in it. What do I mean by that? Well, think about Hell. What do you know about it? It's a bad place where bad people go, right? Well, that's not the case in STRATUM. I don't want to describe such a world. In STRATUM, there is a reason for everything, especially for the way Hell is what it is in the game. "Hell" is called The Black Stratum in the game.
      This world is not very different from Earth, but it is governed by different natural laws.
      The story will also involve the reason why this world entered in touch with ours.

       
      What do you think about all that I said? Would you be interested in such a game? I have to say that everything is just a work of fiction made with my imagination. I do not want to offend anyone's beliefs.
      I want this to be a one man game. I have been working alone on it (this was my decision from the beginning) from art to effects to programming to music to sound effects to everything.
      I also have a youtube video HERE if you want to see the way the game moves and the way my music sounds.
      Please, any kind of feedback will be highly appreciated. If you have something bad to say, do it, don't keep it for yourself only. I want to hear anything that you don't like about my project.
       
    • By LimeJuice
      Hi, it's my first post on this forum and I would like to share the game I am working on at the moment.
      Graphics have been made with Blender3D using Cycle as a renderer and I am using Unity3D. It's a 2D game, one touch side-scrolling game for iOS and Android.
      Here some pictures, and you can have a look to the gameplay on this video :
      Feedbacks ?
      And if you want to try it, send me your email and I will add you to the beta tester list!
       
       








    • By Kirill Kot
      An adventure indie game with quests in a beautiful, bright world. Characters with unique traits, goals, and benefits. Active gameplay will appeal to players found of interactivity, especially lovers of quests and investigations.
      Available on:
      Gameroom (just open the web page and relax)
      AppStore
      GooglePlay
      WindowsPhone

  • Popular Now