Sign in to follow this  
Puzzler183

Crossplatform Engine in a DLL/SO?

Recommended Posts

Well, it's come the time to decide. I know I should put my engine in a DLL; however, I'm not entirely sure how the shared object systems work on Mac and Linux beyond loading them. If I can't get it to build into a DLL with one setting and then a quick change will let me build a shared object, I won't do it since I want this to be crossplatform. So my question is, what have your experiences been with making something dynamically linkable accross platforms? And does anyone know of a good refernce for making shared objects on Mac/Linux other than what Google returns?

Share this post


Link to post
Share on other sites
Are you using Visual Studio for your Windows development? If so, then you are not going to be able to just do a "quick change", but rather will have to set up two entirely separate build environments. You can also install cygwin on Windows and use gcc as your development environment, but you will lose the debugging capabilities of VS (though you do get gdb).

Personally, I'd still go the route of VS on Windows and gcc for your Unix ports. It's not really that big of a deal.

However, if this is your first game engine, then I'd scrap crossplatform all together and just focus on getting a good engine for a single platform. Learn the lessons, and then write a new engine that is multiplatform.

Best of luck!

Jeff

Share this post


Link to post
Share on other sites
A Portable DLL/SO Solution is an article that answers most of your questions. Alternatively, read the man pages for dlopen, dlsym, etc., which are the equivalents of Windows's LoadLibrary functions. To answer your fundamental question, it's not that hard. :-) A few differences in the compilation method, obviously, especially between VC and gcc, but the concepts are all the same. I recommend you go for it.

-bodisiw

Share this post


Link to post
Share on other sites
I know I'll have to set up two build environments for the two; the goal is to have as little code changing as possible. I used Dev-C++ and GCC because I like it a lot more than VS (and I have the most recent VS, legally, so please don't say to try the latest one). For the general record, I'm not exactly a newbie; I've just never bothered to put my stuff in a DLL before.

I know about how to load and that under linux; I've just never made a shared object. That article looks like something good though so I'll give it a read.

EDIT: The article had exactly what I needed. Thank you.

Share this post


Link to post
Share on other sites
I'd love to know why you feel that a DLL/SO is so much better than a static library?

The binary will not be compatible between platforms anyway. There is no point in making it as a dynamic library, it will just serve to cause confusion.

Creating a static library places no overheads on development - there isn't anything you can't do with a static library. So just use one of those instead.

Mark

Share this post


Link to post
Share on other sites
I was actually hoping to make both; I suppose though I at least need a library. I'm not exactly sure how to compile just a library, however, since I'm not experienced with DLL's or libraries beyond loading and using them.

Hmmm... So say I just made a library with that build option. I would still need the header files I have for all the class definitions and that; would the library be able to handle having methods in it? And do I need any special export options for a library?

Share this post


Link to post
Share on other sites
Quote:
Original post by markr
I'd love to know why you feel that a DLL/SO is so much better than a static library?

The binary will not be compatible between platforms anyway. There is no point in making it as a dynamic library, it will just serve to cause confusion.

Creating a static library places no overheads on development - there isn't anything you can't do with a static library. So just use one of those instead.

Mark


Ok, here is why a shared library is so much better than a static library:

1. Compiling dependancies. With a static library, any change to your library code requires a complete recompile of the executable. I'll assume that you understand the enormous consequences of this action.

2. Following from 1), swapping sub-systems and memory requirements. When you can at run-time load in only the libraries you need (aka, D3D library vs Ogl library), you are saving resources.

I'm not sure how using a shared library causes any sort of confusion whatsoever, and deducing from point #1, using a static library causes INCREDIBLE development overhead. With static libraries, you can't have a team working on the renderer with another team working on the sound system, with another team working on the gameplay. It's all about Modularity, only making systems interact where they are absolutely needed.

Anyway, to help the thread-starter, and others who might not know, it's very easy to set up a build system to create a platform specific library. Yes, .dll's built on Windows are not compatable on a Linux system, but it's easy to build the required libraries when needed. As a developer who uses Linux, I'm a huge fan of the command-line. Look into tools like Automake and SCons for easily creating the respectable libraries for the platform you're compiling on.

As for actually creating a library, with VS it's pretty easy, and there are plenty of tutorials about how to export classes and functions (search for __declspec, which is Windows specific. Linux and Mac don't need a special keyword).

And just as an example, in my game engine I will be statically linking the core library to the executable (as there really is no cleaner way to do this) and having all my subsystems (renderer, sound system, etc) in their own shared libraries, pulling them in run-time as needed.

Share this post


Link to post
Share on other sites
Quote:
Original post by JamesKilton
Ok, here is why a shared library is so much better than a static library:

1. Compiling dependancies. With a static library, any change to your library code requires a complete recompile of the executable. I'll assume that you understand the enormous consequences of this action.


I'm not following what the enormous consequences are?

Any change to the static library code will require a recompile of any code that depends on the changes made to the library, and the relinking of the executable.

If the library code is a dynamic library, all code that depends on the changes will still need to be recompiled.

So the gain is no linking step and only if there are absolutely no depencies on the changed code.

I'm happy to hear that I'm missing something.

Quote:

2. Following from 1), swapping sub-systems and memory requirements. When you can at run-time load in only the libraries you need (aka, D3D library vs Ogl library), you are saving resources.


This is true. You also gain in being able to distribute new subsystems, or patches for only the subsystem to your endusers. Of course, you now have to manage all of the versions of the various DLL's and the main executable to make sure you have the user properly patched all around. Not a big deal, but it is a harder problem than simply patching one executable.

Basically, version 1.20 loses meaning as you now have version 1.20 main executable, version 2.0 D3D renderer, etc.. This can cause huge problems for support.

Quote:

I'm not sure how using a shared library causes any sort of confusion whatsoever, and deducing from point #1, using a static library causes INCREDIBLE development overhead. With static libraries, you can't have a team working on the renderer with another team working on the sound system, with another team working on the gameplay.


I'm not sure how this follows at all. You can still have separate systems under a static library system. Being static or shared in no way forces a development style on you. There really isn't anything that prevents you from having multiple teams and people working on various aspects of the engine.


Quote:

It's all about Modularity, only making systems interact where they are absolutely needed.


On this we agree 100%. Messing this up is a huge portion of the troubles development teams encounter. I also do feel that using shared libraries nudges people in this direction, but it certainly isn't necessary in order to get people to write good interfaces to the various subsystems.

Quote:

And just as an example, in my game engine I will be statically linking the core library to the executable (as there really is no cleaner way to do this) and having all my subsystems (renderer, sound system, etc) in their own shared libraries, pulling them in run-time as needed.


Best of luck with your engine, I hope it turns out great!

Jeff

Share this post


Link to post
Share on other sites
Quote:
Original post by jwthomp
I'm not following what the enormous consequences are?

Any change to the static library code will require a recompile of any code that depends on the changes made to the library, and the relinking of the executable.

If the library code is a dynamic library, all code that depends on the changes will still need to be recompiled.

So the gain is no linking step and only if there are absolutely no depencies on the changed code.

I'm happy to hear that I'm missing something.



The point of a shared/dynamic library is that you don't have to ever touch other code using that library UNLESS you're either a crappy programmer or the design was so bad that you had to change your API. That's the point of a library, a public API which doesn't change while the internals are hidden and not connected to anything outside. While this works with a static library as well, again, such interconnectedness is a Bad Thing(tm). Do you understand that?

Quote:

This is true. You also gain in being able to distribute new subsystems, or patches for only the subsystem to your endusers. Of course, you now have to manage all of the versions of the various DLL's and the main executable to make sure you have the user properly patched all around. Not a big deal, but it is a harder problem than simply patching one executable.

Basically, version 1.20 loses meaning as you now have version 1.20 main executable, version 2.0 D3D renderer, etc.. This can cause huge problems for support.


What's wrong with a single system version number? This feels like getting too bogged down in the details. Keeping of versions of everything, I feel, isn't necessary.

Quote:

I'm not sure how this follows at all. You can still have separate systems under a static library system. Being static or shared in no way forces a development style on you. There really isn't anything that prevents you from having multiple teams and people working on various aspects of the engine.


I think I had my mind wrapped around something else. You're right, it's just that I'm against the need to relink any executable.


Quote:

And just as an example, in my game engine I will be statically linking the core library to the executable (as there really is no cleaner way to do this) and having all my subsystems (renderer, sound system, etc) in their own shared libraries, pulling them in run-time as needed.


Best of luck with your engine, I hope it turns out great!

Jeff[/quote]

Thanks.

Share this post


Link to post
Share on other sites
I don't think people are getting the point. I know that a DLL can only be used on windows and that you use shared objects on Linux. The thing I'm trying to figure out is:

1) Should I make one instead of just compiling with the engine code?
2) Which to make (or both)?
3) Which to use for my purposes?
4) How are classes exported under both Windows and Linux?

Share this post


Link to post
Share on other sites
Quote:
Original post by Puzzler183
1) Should I make one instead of just compiling with the engine code?
2) Which to make (or both)?


Choose to make a dynamic or a static library. Don't try to make both work, it's additional overhead.

Quote:

3) Which to use for my purposes?


Without knowing exactly what your purposes are, from my highly biased and incredibly holy opinion, I'd say use a static library. Bear in mind that this is my opinion, and no amount of flames can alter it.

Quote:

4) How are classes exported under both Windows and Linux?


It can be done. With static libraries, it is trivial (no source changes are required). With dynamic libraries, in win32 you need some extra bits in certain places. I'm sure there are plenty of resources out there explaining exactly what they are and where you need to put them.

Bear in mind, whatever you decide, figuring out linker idiosyncracies is likely to be much easier than writing your engine. I wish you the best of luck with it.

Mark

Share this post


Link to post
Share on other sites
Quote:
Original post by JamesKilton
The point of a shared/dynamic library is that you don't have to ever touch other code using that library UNLESS you're either a crappy programmer or the design was so bad that you had to change your API.


In a game development cycle, this is likely to only become true either late in the cycle, or after a library has been used through several cycles and has a standard use by the developers. Even this is likely to change from project to project. It sucks, but it really is the nature of things.

This doesn't forgive not writing solid interfaces and maintaining separation, but the reality is that even interfaces will likely have to change occassionally due to requirements changes, etc. The separation means that because the code base isn't rigid, and you should be able to fairly readily change the locations where the public API's are used and get through the interface with a minimum of pain.



Quote:

That's the point of a library, a public API which doesn't change while the internals are hidden and not connected to anything outside. While this works with a static library as well, again, such interconnectedness is a Bad Thing(tm). Do you understand that?


I guess I'm missing why linking a static library into the executable is an "innately" bad thing? As you've agreed, the benefits of a fixed public API are still there in a static library.

Now if you are talking about the desire to ship a binary only library with a public API for use by external developers (you are selling a library) that is going to be used by many executables, then a shared library might be better due to executable size reduction.

This is also particularly true for developers who will be distributing an executable over the wire that uses your DLL, thus saving costs on bandwidth (assuming the DLL is already installed on host computers).

Quote:

What's wrong with a single system version number? This feels like getting too bogged down in the details. Keeping of versions of everything, I feel, isn't necessary.


The problem with a single version number is that you have no way of knowing if the customer has grabbed a copy of one of the DLL's that is an older version and is using it with a newer version executable. If you have no way to know what each components version is, customer support won't know exactly what the customer is running.

Quote:

I think I had my mind wrapped around something else. You're right, it's just that I'm against the need to relink any executable.


No worries, my mind gets wrapped around all kinds of nasty stuff. :)

If you don't like re-linking, then I agree that shared libraries are the way to go.

Cheers!

Jeff

Share this post


Link to post
Share on other sites
Quote:
Original post by Puzzler183
I don't think people are getting the point. I know that a DLL can only be used on windows and that you use shared objects on Linux.


Sorry, let me be more direct.


Quote:

The thing I'm trying to figure out is:

1) Should I make one instead of just compiling with the engine code?


What do you hope to gain from shared libaries? From static libraries? How will they impact your engine?

One reason to use shared libraries is if you want to choose between two or more implementations of a component at run time (for example OpenGL or D3D), but don't want them to both be resident in memory at the same time.

Quote:

2) Which to make (or both)?


What you should do is write an API that is used to load up each component. The instance of this API will handle the details (in a hidden fashion), allowing you to load the component from a statically linked library, or to first load it into memory via a DLL and then create the component. This allows you to do one now, and the other later.

This is pretty much just a factory pattern. I'd just do one implementation for now (if not forever).

Quote:

3) Which to use for my purposes?


What are your purposes? All I know is that you are making an engine (this is a bit nebulous), and that you that you are interested in cross platform support. Doing dynamics doesn't really gain you much in cross platform support as you have to write the code either way. The benefits largely come from writing your components correctly so that they can be easily ported.

Quote:

4) How are classes exported under both Windows and Linux?


What do you mean? How do you access a class in a library?

One way in a DLL is at:

http://www.codeproject.com/dll/SimpleDll2.asp

Or you can write some standard C functions in each library that can give you instances of the classes for you. I'm pretty fond of doing a simple COM based system to get instances from a library (basically a class factory, and it's portable).

Best of luck!

Jeff

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