Sign in to follow this  

C++ Dll to C++

This topic is 3144 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

Hi all. I'm trying to rewrite an engine of mine and I tough I'd put it into a DLL. This is because later on I'd like to have it working in C# as well. I know how to export a normal function like "int RandomNumber() { return rand();}" or a variable but those won't help me. I'd like to have classes exported. Untill now I've understood how this thing works "#ifdef DLLTEST_EXPORTS #define DLLTEST_API __declspec(dllexport) #else #define DLLTEST_API __declspec(dllimport) #endif" but from what I read on the internet only the same version of visualC++ can compile that and that's a big nono for me. I'm not worried about the classes themselves as I'd like to introduce a procedural style of work first. (Functions like PositionEntity(CEntity ent,CVec3 vec); ). But how would I export a function like that. It needs to know what a CEntity is and what a CVec3 is and thus I'd have to export the classes right? If someone could help me I'd be very thankfull.

Share this post


Link to post
Share on other sites
Quote:
Original post by LorinAtzberger
from what I read on the internet only the same version of visualC++ can compile that and that's a big nono for me.
That's a fact of life with C++ - there is no standard for how the binary should look AFAIK, so a C++ DLL built with one compiler won't necessarily work with another compiler.

You've got to define a procedural interface with plain C functions for that to work.
Quote:
I'm not worried about the classes themselves as I'd like to introduce a procedural style of work first. (Functions like PositionEntity(CEntity ent,CVec3 vec); ).
But how would I export a function like that. It needs to know what a CEntity is and what a CVec3 is and thus I'd have to export the classes right?
Instead of passing by value (e.g. func( CEntity ) ), pass by pointer (e.g. func( CEntity* ) ), and then all the compiler needs to know is that such a class exists - it doesn't need to know anything about it.

Share this post


Link to post
Share on other sites
I was anyway going to place pointers there but I forgot to write them here.
So how do I tell the compiler that such a class exists?

Here is my code for the engine.
If I can get this up running from the DLL then I can figure out the rest.

class CEngine
{
private:
bool m_FullScreen; // Set full screen as default
HWND m_HWnd; // This is the handle for the window
RECT m_Rect; // This holds the window dimensions
HDC m_HDC; // General HDC - (handle to device context)
HGLRC m_HGLRC; // General OpenGL_DC - Our Rendering Context for OpenGL
int m_Depth;

public:
CEngine(HWND hWnd)
{
m_HWnd = hWnd;
GetClientRect(hWnd,&m_Rect);
m_HDC = GetDC(hWnd);
m_Depth = 32;
SetupPixelFormat(m_HDC);
m_HGLRC = wglCreateContext(m_HDC);
wglMakeCurrent(m_HDC,m_HGLRC);
SizeOpenGLScreen(m_Rect.left -m_Rect.right,m_Rect.top -m_Rect.bottom);

}

private:
bool SetupPixelFormat(HDC dc)
{
PIXELFORMATDESCRIPTOR pfd = {0};
int pixelformat;

pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR); // Set the size of the structure
pfd.nVersion = 1; // Always set this to 1
// Pass in the appropriate OpenGL flags
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.dwLayerMask = PFD_MAIN_PLANE; // We want the standard mask (this is ignored anyway)
pfd.iPixelType = PFD_TYPE_RGBA; // We want RGB and Alpha pixel type
pfd.cColorBits = m_Depth; // Here we use our #define for the color bits
pfd.cDepthBits = m_Depth; // Depthbits is ignored for RGBA, but we do it anyway
pfd.cAccumBits = 0; // No special bitplanes needed
pfd.cStencilBits = 0; // We desire no stencil bits
if ( (pixelformat = ChoosePixelFormat(m_HDC, &pfd)) == FALSE )
{
MessageBox(NULL, L"ChoosePixelFormat failed", L"Error", MB_OK);
return FALSE;
}

// This sets the pixel format that we extracted from above
if (SetPixelFormat(m_HDC, pixelformat, &pfd) == FALSE)
{
MessageBox(NULL, L"SetPixelFormat failed", L"Error", MB_OK);
return FALSE;
}

return TRUE;
}

void SizeOpenGLScreen(int width,int height)
{
if(height==0)
height=1;
glViewport(0,0,width,height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f,(float)width/(float)height,1,150.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

void ClearDevice()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear The Screen And The Depth Buffer
}
public:
void Render()
{
ClearDevice();
SwapBuffers(m_HDC);
}
};
typedef CEngine * TEngine;

TEngine CreateEngine(HWND hWnd)
{
return new CEngine(hWnd);
}
void Render()
{
}
void Render(TEngine eng)
{
eng->Render();
}

Thank you! You are very helpfull

Share this post


Link to post
Share on other sites
Quote:
Original post by LorinAtzberger
I was anyway going to place pointers there but I forgot to write them here.
So how do I tell the compiler that such a class exists?



I'm sorry, I don't really have time to read the code but I can answer this question for you.

What you want is something called "Forward declaration"


Basically before you declare a pointer variable in your code you just write:

class CEntity;

That just tells to the compiler that such a class exists somewhere and at some point it will get defined. That is enough for the compiler to understand declarations of form:

CEntity *pEnt;

All pointers are essentially the same, the compiler just needs to know that CEntity is some kind of class.

Share this post


Link to post
Share on other sites
Quote:
Original post by LorinAtzberger
But from what I read on the internet only the same version of visualC++ can compile that and that's a big nono for me.


Why is it a nogo for you? Do you plan to release binaries only for others to use? Well... simply offer binaries for the most common compilers.
If that's not the case why do you care?

To export a class:

class DLLTEST_API foo
{};



I'll ask again. Why is it a nogo for you? If you're the only one working on your engine then just stick with a c++ approach and forget the COM approach (for gods sake, don't overcomplicate things if it's not even necessary).

Share this post


Link to post
Share on other sites
When you create a DLL that's to be consumed from multiple languages, you need to use an agreed binary interface - the most common ones are the C ABI, COM+ and the Microsoft CLR (.NET).

Quote:
Original post by SiS-Shadowman
Why is it a nogo for you? Do you plan to release binaries only for others to use? Well... simply offer binaries for the most common compilers.


This approach is pretty useless. You don't need to release seperate DLLs for each compiler, you need to release seperate DLLs for each compiler option that affects either the binary interface; for Visual Studio you need [Release|Debug]*[Static CRT|Dynamic CRT]*[Checked STL | Unchecked STL] - that's 8 versions just for the commonly altered options.

And then you still can't use it from C# without either creating either a C or C++/CLI wrapper.


Share this post


Link to post
Share on other sites
Please note that passing an object as a pointer doesn't solve anything.

You're passing from one binary to another, a pointer to a piece of memory that represents an object.

If the compilers doesn't agree on that exact memory layout to be an object, there will be a problem (member alignment, order optimizations, v-table location etc).


Share this post


Link to post
Share on other sites

This topic is 3144 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.

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