• Welcome to Theos PowerBasic Museum 2017.

Translating PB's CALL DWORD @@pthis[2] to C/C++, how?

Started by Patrice Terrier, April 06, 2013, 03:50:37 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Patrice Terrier

I would like to convert this piece of PB's code to C/C++, but i don't know how to do it.
Could you help?

FUNCTION IUnknown_Release (BYVAL pthis AS DWORD PTR) AS DWORD
    LOCAL DWRESULT AS DWORD
    IF pthis THEN
       CALL DWORD @@pthis[2] USING IUnknown_Release(pthis) TO DWRESULT
       FUNCTION = DWRESULT
    END IF
END FUNCTION
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Peter Weis

#1
Hi Theo,

but not 2 bytes 8 bytes

pThis[0] offset 0 bytes
pThis[1] offset 4 bytes
pThis[2] offset 8 Bytes

You look at the test example


#COMPILER PBCC
#COMPILE EXE
#DIM ALL

FUNCTION PBMAIN () AS LONG

    DIM a (0 TO 10) AS DWORD
    a(0) = 1
    a(1) = 2
    a(2) = 3

    LOCAL b AS DWORD PTR
    LOCAL c AS DWORD PTR
    b = VARPTR(a(0))
    c = VARPTR(b)


    testf(c)

    WAITKEY$

END FUNCTION

SUB testf(BYVAL b AS DWORD PTR)

    PRINT @@b[2]


END SUB     




Patrice Terrier

In my case, pthis, is a stream pointer got from CreateStreamOnHGlobal(MemBuffer, FALSE, pthis)

long IUnknown_Release (IN LPSTREAM* pthis) {
    long NewReferenceCount = -1; // Means error
    if (pthis) {
         // what syntax should i use there?
    }
    return NewReferenceCount;
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Peter Weis

#3
Hello Patrice Terrier
Since I unfortunately do not exercise more in C + +. I can only give you the tip you leave that translate from FreeBASIC with the C-emitter

The design is similar but the syntax is different!

Patrice Terrier

Is that something that would make sense?

long IUnknown_Release (IN LPSTREAM* pthis) {
    long NewReferenceCount = -1;
    if (pthis) {
        typedef long (__stdcall *zProc) (LPSTREAM*);
        zProc hProc = (zProc) pthis[2];
        if (hProc) { NewReferenceCount = hProc(pthis); }
    }
    return NewReferenceCount;
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Peter Weis


José Roca

Use IStream_Release(pthis).

IStream_Release is a macro defined in objidl.h.

José Roca

BTW the release method returns a DWORD, not a LONG.

José Roca

Alternatively, you can use
(pthis)->lpVtbl -> Release(pthis)

Charles Pegge

Another variation:

typedef struct _fUnknown
{
HRESULT (*QueryInterface)(void* pvObject, REFIID riid, void **ppvObject);
ULONG (*AddRef)(void* pvObject);
ULONG (*Release)(void* pvObject);
} fUnknown,*pfUnk;



ULONG ReleaseObject(pfUnk*pthis)
{
if (pthis)
{
  return pthis[0]->Release(pthis);
}
}

Patrice Terrier

#10
Ok, thanks to all of you.

But just for my learning, do you think that my syntax could work with this COM thing?

long IUnknown_Release (IN LPSTREAM* pthis) {
    long NewReferenceCount = -1;
    if (pthis) {
        typedef long (__stdcall *zProc) (LPSTREAM*);
        zProc hProc = (zProc) pthis[2];
        if (hProc) { NewReferenceCount = hProc(pthis); }
    }
    return NewReferenceCount;
}
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Patrice Terrier

Charles

Does your code variation is intended to work on both 32 and 64-bit ?

...
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Mike Stefanik

#12
I'd recommend just using CComPtr<IStream> and let it take care of the reference counting. Unless you're actually coding in plain C, you might as well take advantage of smart pointers for COM objects. I think this is where you can start getting into trouble if you simply do a line-by-line, verb-for-verb translation. Instead, consider what you're trying to do and see if there's a better way (easer to read, easier to maintain). When it comes to do with anything that has to deal with COM, I can guarantee you that ATL will make your coding appreciably easier.

Edit: Today is apparently not a good spelling day for me.
Mike Stefanik
sockettools.com

Patrice Terrier

#13
Form my learning, could you please answer to my question, if you understand the small code i posted, thanks?

So far, my verb for verb translation is the way i am learning, and the way i understand my own code ;)
Patrice Terrier
GDImage (advanced graphic addon)
http://www.zapsolution.com

Charles Pegge

#14
Quote from: Patrice Terrier on April 07, 2013, 12:49:13 AM
Charles

Does your code variation is intended to work on both 32 and 64-bit ?

...

Certainly. The trick is to ensure that pointers are always expressed as pointers, and are never dereferenced to an integer or some other number.

Your example requires an extra dereferencing step before using accessing the function array. The equivalent to my previous example looks like this:

int ReleaseObjectA(void*pthis)
{
if (pthis)                  // valid COM object pointer
{
  void**ppfunc=pthis;        //address object body
  void**pfunc=*ppfunc;       //address function table
  ULONG (*Release)(void*pthis);   //declare function
  Release= pfunc[2];        //assign function address by index
  return Release(pthis);     //make call with object
}
}