October 31, 2025, 11:52:49 AM

News:

IWBasic runs in Windows 11!


trying to use a c++ class in Emergence

Started by fasecero, May 25, 2009, 05:11:23 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

fasecero

I made a dll for Emergence that use classes of a c++ dll.

In order to manage the creation and destruction of those classes I used linked lists, it works well, but I think it would be possible to gain speed if we could pass directly a pointer to the class to Emergence, and when we want to use the class pass the pointer again the dll.
I don't know even if is posible, but I tried without success ...

The class of the dll made in C ++ is:

class hgeColorRGB
{
public:
float r,g,b,a;

hgeColorRGB() { r=g=b=a=0; }
void SetHWColor(DWORD col);
DWORD GetHWColor();
};


to create multiple instances of the class hgeColorRGB and use its methods in Emergence, I made the following functions:

extern "C" void* __declspec(dllexport) hge_ColorRGB_Create(float red, float green, float blue, float alpha) {
   void* pvoid;
   hgeColorRGB *p;
   
   pvoid=new hgeColorRGB();
   p=(hgeColorRGB *) pvoid;
   
   // set the members
   p->a=alpha;
   p->r=red;
   p->g=green;
   p->b=blue;

   // return the pointer
   return pvoid;
}

extern "C" void __declspec(dllexport) hge_ColorRGB_Delete(void* pvoid) {
   hgeColorRGB *p;
   p=(hgeColorRGB *) pvoid;
   
   delete p;
}

extern "C" void __declspec(dllexport) hge_ColorRGB_Get(void* pvoid, float &red, float &green, float &blue, float &alpha) {
   hgeColorRGB *p;
   p=(hgeColorRGB *) pvoid;
     
   red=p->r;
   green=p->g;
   blue=p->b;
   alpha=p->a;
}

extern "C" DWORD __declspec(dllexport) hge_ColorRGB_Set(void* pvoid, DWORD color, float alpha) {
   hgeColorRGB *p;
   p=(hgeColorRGB *) pvoid;
   
   p->a=alpha;
   p->SetHWColor(color);
   
   return color; // just to check
}


and in Emergence i use the declarations:

DECLARE CDECL IMPORT, hge_ColorRGB_Create(float red, float green, float blue, float alpha), HCOLOR
DECLARE CDECL IMPORT, hge_ColorRGB_Set2(HCOLOR col, uint rgbcolor, float alpha), uint
DECLARE CDECL IMPORT, hge_ColorRGB_Delete(HCOLOR col)



when i test the functions in Emergence, all the operations over the members seems to work but trying to call any method fail, for example when i use hge_ColorRGB_Set:

   p->a=alpha;                     <---- OK
   p->SetHWColor(color);      <---- FAIL

What can i do?


Ionic Wind Support Team

You're missing something there.  How did you declare the class in Emergence?

Whether you can make it work depends entirely on the C++ compiler you are using, and whether the designer used a standard vtable format.  The implementation of which is up to the whim of the designer.

Paul.
Ionic Wind Support Team

fasecero

' Hi Paul, this is my idea:

pointer col
float red, gree, blue, alpha

' the C dll create a instance of hgeColorRGB dynamically and return to ebasic a *void pointer:
col=hge_ColorRGB_Create(1, 2.5, 0.2, 0.8)

' when i want to use the created instance, i pass back the pointer to the C dll:
hge_ColorRGB_Get(col, red, green, blue, alpha)


col is a *void pointer for EB, so i thought it is not necessary to declare the class in EB.
when i pass the pointer to the C dll, there i cast it to hgeColorRGB.


Ionic Wind Support Team

Maybe I was not understanding you then.  You're not using a C++ class from Emergence, you are using an exported cdecl function and your DLL is crashing within the C++ code, correct?


DECLARE CDECL IMPORT, hge_ColorRGB_Create(float red, float green, float blue, float alpha), HCOLOR

Where is HCOLOR defined?  Shouldn't it be:

DECLARE CDECL IMPORT, hge_ColorRGB_Create(float red, float green, float blue, float alpha), POINTER
DECLARE CDECL IMPORT, hge_ColorRGB_Set2(POINTER col, uint rgbcolor, float alpha), uint
DECLARE CDECL IMPORT, hge_ColorRGB_Delete(POINTER col)

Paul.
Ionic Wind Support Team

fasecero

Quoteyou are using an exported cdecl function

Yes Paul. I forgot about HCOLOR, is defined somewhere like:

TYPEDEF HCOLOR pointer

I made an example more simple, where the objective is the same and it works perfectly, I do not know what is wrong with my original code ...

I have a dll developed in C ++ which has a class.
To been able to use the class in EB I create 2 functions in the same dll, which will be exported:


class DLLCLASS {
public:
float var;

void  Set_var(float v) { var=v; }
float Get_var()        { return var; }
};

extern "C" void __declspec(dllexport) SETVAR(void* pvoid, float v) {
    DLLCLASS *p;
    p=(DLLCLASS *) pvoid;
   
    p->Set_var(v);
}

extern "C" float __declspec(dllexport) GETVAR(void* pvoid) {
    DLLCLASS *p;
    p=(DLLCLASS *) pvoid;
   
    return p->Get_var();
}


Furthermore, I want to manage the creation and destruction of instances of this class in EB. So, I add 2 more functions, wich are also exported, one create an instance and return its pointer, and the other destroy the instance:


extern "C" void* __declspec(dllexport) CREATE(float v) {
    void* pvoid;
    DLLCLASS *p;
   
    pvoid=new DLLCLASS;
    p=(DLLCLASS *) pvoid;

    p->Set_var(v);

    return pvoid;
}

extern "C" void __declspec(dllexport) DESTROY(void* pvoid) {
    DLLCLASS *p;
    p=(DLLCLASS *) pvoid;
   
    delete p;
}


Finally I use the dll in Emergence Basic:



$USE "Dllclass.lib"

DECLARE CDECL IMPORT, CREATE(float v), pointer
DECLARE CDECL IMPORT, SETVAR(pointer pclass, float v)
DECLARE CDECL IMPORT, GETVAR(pointer pclass), float
DECLARE CDECL IMPORT, DESTROY(pointer pclass)

OPENCONSOLE
PRINT "THIS WORK PERFECT!!"
PRINT ""

pointer pclass
pclass=CREATE(10.0)
PRINT "Instance created in the dll and assigned with: "+ STR$( GETVAR(pclass) )

SETVAR(pclass, 250.0)
PRINT "Instance now assigned with: "+ STR$( GETVAR(pclass) )

DESTROY(pclass)

PRINT ""
PRINT "Pess any key to close"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE
END


Testing this example everything works perfectly, but in the code originally posted I still can't find what is wrong ...
Well, at least seems I can do it! :), thanks.
Just in case, I attached a zip with this little experiment.


sapero

fasecero, if you define all methods as virtual __stdcall, you'll be able to call the methods directly from Ebasic// c++
class hgeColorRGB
{
public:
hgeColorRGB();
// nonstandard interface methods
virtual STDMETHODIMP_(void)  SetHWColor(DWORD col);
virtual STDMETHODIMP_(DWORD) GetHWColor();
//todo
};
hgeColorRGB::hgeColorRGB() {todo}
void  hgeColorRGB::SetHWColor(DWORD col) {todo}
DWORD hgeColorRGB::GetHWColor() {todo}

extern "C" BOOL __declspec(dllexport) Create(hgeColorRGB **ppv)
{
*ppv = new hgeColorRGB;
return *ppv != 0;
}

// ebasic
interface hgeColorRGB
stdmethod SetHWColor(DWORD col)
stdmethod GetHWColor(),DWORD
endinterface

declare cdecl import,Create(pointer ppv),BOOL

hgeColorRGB p
Create(&p)
p->SetHWColor(5)
// todo: delete

fasecero

Sapero, this can save me a lot of work, no doubt i will use it.