Borland style __closure in gcc
Asked Answered
P

2

6

I am new in programming with gnu C++. I have an application which I thought to be converted to cross platform and I began to use C::B about two months ago. I had many problems but I solved them keeping original code in #ifdef BCB ... #else ... #endif blocks for objects classes or structs. I am not able to solve the following problem because it is very complicated. The function declarations have been working since 1997/1998 and every point of the application(s) was developed relying on these definitions and implementations. They are used for inter-object, inter-process, and network communication and all interactive event system. Any function anywhere can be called with any number (up to 50) of parameters directly, or via stream connections as long as our JetRtl.dll is ready to serve and caller knows the number of parameters. I explained so long because as far as I see, many people simply ask "Why ...", or give childish solution to be worked only in "Hello World" apps.

Here is the header file. #else .... #endif section has been recently added.

#ifndef fcalls_h
#define fcalls_h

#include <jettip.h>
#include <stdarg.h>

//  CM_FN_.. calls non member F(...), (ecx & 4) == 0
#define CM_FN_C 0x8FF0 // __cdecl non member F(...)
#define CM_FN_F 0x8FF1 // __fastcall non member F(...)
#define CM_FN_P 0x8FF2 // __pascal non member F(...)
#define CM_FN_S 0x8FF3 // __stdcall non member F(...)

//  CM_FNX.. calls  member X::F(...), (ecx & 4) == 4
#define CM_FNXC 0x8FF4 // __cdecl member X::F(...)
#define CM_FNXF 0x8FF5 // __fastcall member X::F(...)
#define CM_FNXP 0x8FF6 // __pascal member X::F(...)
#define CM_FNXS 0x8FF7 // __stdcall member X::F(...)

#define CM_TERK 0xFFFE // Quits message loop
#define CM_DELW 0x8FFF // destroy link window

typedef void __cdecl    (*JF_C)();
#ifdef BCB
typedef void __cdecl    (__closure *JFXC)();
#else
template<class T> class FXT{};
template<class R> class FXT<R()>{};
template<class R,class A> class FXT<R(A)>{};
template<class R,class A,class B> class FXT<R(A,B)>{};
template<class R,class A,class B,class C> class FXT<R(A,B,C)>{};
template<class R,class A,class B,class C,class D> class FXT<R(A,B,C,D)>{};
template<class R,class A,class B,class C,class D, class E> class FXT<R(A,B,C,D,E)>{};
template<class R,class A,class B,class C,class D, class E,class F> class FXT<R(A,B,C,D,E,F)>{};
template<class R,class A,class B,class C,class D, class E,class F,class G> class    FXT<R(A,B,C,D,E,F,G)>{};

typedef FXT<void __cdecl (void*)> JFXC;
#endif

JF_C __cdecl F_CP(...);
JFXC __cdecl FXCP(...);
JF_C __cdecl _F_CP(int yer, ...);
JFXC __cdecl _FXCP(int yer, ...);

long __fastcall RunFN_C(va_list list, long args);
long __fastcall RunFN_F(va_list list, long args);
long __fastcall RunFN_P(va_list list, long args);
long __fastcall RunFN_S(va_list list, long args);

long __fastcall RunFNXC(va_list list, long args);
long __fastcall RunFNXF(va_list list, long args);
long __fastcall RunFNXP(va_list list, long args);
long __fastcall RunFNXS(va_list list, long args);

// Dispatches the function call into appropirate function; fnx(list, args)
long  __fastcall JetTip DispCall(va_list list, long args, int call);

#endif

The big question is "How can I make GCC (MinGW 4.71, I also have 4.92) to understand the expression typedef void __cdecl (__closure *JFXC)();?"

Expressions without __closure compiles and works as expected.

Peplum answered 4/1, 2015 at 19:23 Comment(10)
C++11 has lambdas. Does that not replace the closures well enough?Wilderness
Also, C++11 has variadic templates, which seems like it could/should replace some of your code.Wilderness
Don't worry; this is a reasonable question, well asked.Engineman
@VáclavZeman Each lambda gets a distinct type. It solves a slightly different problem than C++ Builder's closures. But as you say, C++11 has variadic templates, and with those, it seems to me like it should be possible to define a custom closure<T> class (to be used as typedef closure<void()> JFXC;). It's probably a bit too much to really be suitable for an SO answer, though.Sells
There is also the std::function<>. Is that not useful as well? It seems to me it could just replace the FXT type.Wilderness
@VáclavZeman It depends on how the closures are used, but agreed, it's very well possible that that already covers it well enough.Sells
Well, it is hard to find good documentation for the __closure keyword. From the few bits I have seen so far it seems like __closure is just pointer to member function that is already bound to class instance. That sounds like something std::function<> and std::bind() can replace easily.Wilderness
Dear Vaclav Zeman, can you supply a very simple example so that I can adjust it to suit my problem. The template deinions I made solved the problem but I have to create functions and repeat the same stuf thousands of time for every function call-request and execution points. It means to build the application from scratch would be easier.Orton
@VáclavZeman Yes, you're right in general, but __closure also has a shared representation across all possible instances that I've seen code rely on. (For instance, some code might set or retrieve the code pointer and the data pointer in a closure object manually.)Sells
It is not clear to me how you use the class FXT so it is hard to suggest a good replacement.Wilderness
W
5

Replacement for __closure

It seems to me that these bits of Borland C++ ...

struct S { void f(){} };
S s;
typedef void __cdecl (__closure *JFXC)();
JFXC jfxc (&(s.f));
jfxc();

... can be replaced by these bits of C++11

struct S { void f(){} };
S s;
typedef std::function<void()> JFXC;
JFXC jfxc (std::bind (&S::f, &s));
jfxc();
Wilderness answered 4/1, 2015 at 19:52 Comment(0)
P
0

I ve resolved my part of the problem. JFXC function type is used to manipulate object methods as pointers (not for calling methods ) and the rest is done by the library (assembler) functions. With gcc, I couldn't assign or typecast any member functions into generic object::method type. The following definitions make it possible but it still has problems when trying to call but at my side as the FNXC types are handled by manually designed/modified assemmbly modules, there is no problem with compilation. The only problem for me is that I hoped gcc to produce assemly code for targetted platforms and architectures. The following changes made for the code above compiles in any case. You can uncomment #ifndef __closure section.

typedef void __cdecl    (*JF_C)();

#ifdef BCB
typedef void __cdecl    (__closure *JFXC)();
#else
class ANY;
/*#ifndef __closure
#   define __closure ANY::
#endif*/
#ifdef __closure
typedef void __cdecl    (__closure *JFXC)();
#else
typedef void __cdecl (*JFXC)(ANY&, void (ANY::*)());
#endif

#endif // BCB

Thanks for everybody replying the post.

Peplum answered 5/1, 2015 at 22:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.