Jump to content
  • Advertisement
Sign in to follow this  
_Sigma

Objects across DLL boundary

This topic is 3604 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Alright - yes, I know this is generally *a bad thing*. My understanding of the situation is that if the object in question being passed over the boundary can be different, ie, two different std::string implementations, problems can arise. However, if the object has the same implementation and the compiler is the same, you can use it across the boundary. Thus, my question is: Lets say I have an class foo that is used in my program, however a DLL needs a pointer to foo and needs to call methods, etc on foo. However, this DLL was written by Joe Blow using gcc and my main program was built using VS2008. Since both implementations are the same, but built with different compilers, am I going to run into *issues*? Appreciate the feedback.

Share this post


Link to post
Share on other sites
Advertisement
If one compiler decided to pad the object differently, decided to implement virtual functions differently, or probably some other cases, you will run into issues.

You can use OO without using classes though. C does this just fine with functions like fopen() and fwrite(): have a function which hands out ownership to a pointer to some opaque type (like FILE *) and require that that pointer is passed into functions in order to perform operations on that object (like fwrite() does).

This is safe because you ensure that the code dereferencing the pointer is the same code which defines what it points to (the code that implements fopen() and fwrite()).

Share this post


Link to post
Share on other sites
It's not a bad thing as far as I'm aware.


Quote:
Original post by _Sigma
My understanding of the situation is that if the object in question being passed over the boundary can be different, ie, two different std::string implementations, problems can arise.
However, if the object has the same implementation and the compiler is the same, you can use it across the boundary.
The main issue with passing objects like a std::string between two DLLs is to do with memory, specifically, it is caused by both DLLs statically linking to the std::string's code.
Internally the string has a char* (or whatever), which points to memory allocated by new. If you then let another DLL use this string object, then the other DLL may call delete on this pointer.

On Windows new/delete pairs must be called from the same DLL. You can't new in one DLL and then delete from another.

If std::string was implemented in its own DLL (instead of using static linking), then everything would be fine - because whenever you called a function on a string object (from any DLL), the memory allocations would always be done in std::strings own DLL.

Quote:
Thus, my question is: Lets say I have an class foo that is used in my program, however a DLL needs a pointer to foo and needs to call methods, etc on foo. However, this DLL was written by Joe Blow using gcc and my main program was built using VS2008. Since both implementations are the same, but built with different compilers, am I going to run into *issues*?
No, not unless you are going to be deleting a pointer in a different DLL than it was allocated in.

However, due to C++ name mangling, I dont think GCC is even capable of properly linking with a DLL produced by VS2008 (unless you use a plain C interface, in which case there's no problems, because it's not C++ anymore...)

Share this post


Link to post
Share on other sites
If i interpret what you are saying correctly. I say you should use Interfaces. I.E., have a base class, then have your DLL instance the the interface with the class it contains, using that method, it should work no matter what compiler you use, not 100% sure, but i have never had a problem with it.

So...


// This abstract class needs to be included in your executable project, and your DLL project.
class BaseClass {
public:
BaseClass() { };
virtual BaseClass()=0;

/*
Virtual Functions here
*/

}

//-----------------------

// This class goes in your DLL.
class DerivedClass : public BaseClass {
public:
DerivedClass();
~DerivedClass();

/*
Declare the virtual functions here
*/

}

/--------------------------

// This also goes inside your DLL.
bool declspec(_dllexport) InstanceFoo(BaseClass** _MyClass) {
if(!*_MyClass)
*_MyClass = new DerivedClass();

return true;
}

// Make a one for deleting the class here.





Share this post


Link to post
Share on other sites
Quote:
Original post by GanonPhantom
If i interpret what you are saying correctly. I say you should use Interfaces. I.E., have a base class, then have your DLL instance the the interface with the class it contains, using that method, it should work no matter what compiler you use, not 100% sure, but i have never had a problem with it.

So...

*** Source Snippet Removed ***
I second interfaces. They're nice and clean, OOPy, and don't expose the underlying implementation of the class to the outside world, which is good for encapsulation.

Share this post


Link to post
Share on other sites
Thanks for the input.

What I'm really looking for here is an easy way to do a plugin system of sorts, wherein a users DLL can get loaded via my program and get passed variables and interact with the main app.

GanonPhantom and Evil Steve - Do you know of any decent examples for this? Must I haven't really done interfaces in C++ like this before.

Share this post


Link to post
Share on other sites
A few things on this. First, if you're sure you're going to be using the DLL in a case where the compiler settings will be compatible, you're okay exporting classes across interfaces. Unfortunately, this isn't as common a case as we would like. The interfaces is an excellent approach, but it obviously depends on what you're doing whether or not that makes sense, as it can be very intrusive on your design; and it still won't work across some different compilers without some extra work. I use interfaces vigorously, when they make sense in my design, but again, it isn't a catch-all.

Another alternative is to do something similar to what SWIG does when exporting to other languages. SWIG basically wraps all the C++ methods in C-style methods. Then, from the calling side, they de-wrap by having a proxy class, which calls the C-style methods. This will work, because while the C++ ABI isn't even close to portable, the C ABI is. Unfortunately, I don't believe SWIG will do this automatically for C++ to C++, so this would take some manual work to export this way. It should be a cleaner solution than COM, though, which, in my experience, has tended to be messy and very intrusive on the design.

Share this post


Link to post
Share on other sites
Quote:
Original post by GanonPhantom
If i interpret what you are saying correctly. I say you should use Interfaces. I.E., have a base class, then have your DLL instance the the interface with the class it contains, using that method, it should work no matter what compiler you use, not 100% sure, but i have never had a problem with it.


Unfortunately that won't work across different compilers. C++ just doesn't have a consistent ABI. COM is something that was really designed for this sort of thing, but it can very awkward to work with (especially if you're not working with MFC or ATL). Also one of the bigger advantages of using a COM-based system, which is letting third-parties author components in Visual Basic, is less of an issue these days in the post-.NET world. Really the easiest solution here is to just make the plugin DLL's use a consistent C interface, and make sure all memory allocation/deallocation is done on the same side of the DLL boundary.

Of course personally I wouldn't have a problem with requiring plugin authors to use Visual C++, but that's just me.

Share this post


Link to post
Share on other sites
Quote:
Original post by MJPmake sure all memory allocation/deallocation is done on the same side of the DLL boundary.

This I can guarantee. The DLL will only be getting points to valid memory.
Quote:

Of course personally I wouldn't have a problem with requiring plugin authors to use Visual C++, but that's just me.

At some point, this will all be cross-platform, so the less rewriting I have to do to achieve this the better. As well, I really don't like shoving a compiler down someone's throat!
Quote:

use a consistent C interface

Just so I'm clear, what do you mean by this exactly?

Share this post


Link to post
Share on other sites
A C interface would be something like described above using a function like fread, where you pass the instance of the object (file handle) to the function on which it is going to preform. If doing this from a dll you have to mark the functions (as you would for a factory create function) as being C.

Personally I only export a create function and not a delete as I like to be able to just call "delete foo" instead of "foo_release(foo)", for an example of how to accomplish this see the following article.

With regards to compiling with gcc and then using this shared object(gcc has no notion of a dll) in a vs it would need recompiling and the same vice versa.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!