- class of unsigned 32 bit and overflow - 6 Updates
- merge C callbacks into C++ class? - 15 Updates
- Could you explain 'type conversions (casts)' in class access control to me? - 2 Updates
asetofsymbols@gmail.com: Jun 02 01:36AM -0700 /* In one asm file compile for result .obj code section _DATA use32 public class=DATA global u32omul global u32oadd global u32osub global i32omul global i32oadd global i32osub section _BSS use32 public class=BSS section _TEXT use32 public class=CODE ;u32 __stdcall u32omul(u32 a, u32 b) ; 0ra, 4P_a, 8P_b align 4 u32omul: mov eax, dword[esp+ 4] cmp eax, -1 je .1 mov edx, dword[esp+ 8] cmp edx, -1 je .0 mul edx cmp edx, 0 je .1 .0: mov eax, -1 .1: ret 8 ;u32 __stdcall u32oadd(u32 a, u32 b) align 4 u32oadd: mov eax, dword[esp+ 4] mov edx, dword[esp+ 8] add eax, edx jnc .0 mov eax, -1 .0: ret 8 ;u32 __stdcall u32osub(u32 a, u32 b) align 4 u32osub: mov eax, dword[esp+ 4] cmp eax, -1 je .1 mov edx, dword[esp+ 8] cmp edx, -1 je .0 sub eax, edx jae .1 .0: mov eax, -1 .1: ret 8 ;i32 __stdcall i32omul(i32 a, i32 b) align 4 i32omul: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 imul edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 ;i32 __stdcall i32oadd(i32 a, i32 b) align 4 i32oadd: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 add eax, edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 ;i32 __stdcall i32osub(i32 a, i32 b) align 4 i32osub: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 sub eax, edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 */ // bcc32 thisfile.cpp asmfile.obj #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> #include <limits.h> #include <iostream.h> #define G(a,b) if(a)goto b #define R return #define P printf #define M malloc #define Fr free #define F for #define S sizeof #define u8 unsigned char #define i8 signed char #define u16 unsigned short #define i16 signed short #define u32 unsigned #define i32 int #define d64 double // functions for detect u32 or i32 overflow in asm extern "C" { u32 __stdcall u32omul(u32 a, u32 b); u32 __stdcall u32oadd(u32 a, u32 b); u32 __stdcall u32osub(u32 a, u32 b); i32 __stdcall i32omul(i32 a, i32 b); i32 __stdcall i32oadd(i32 a, i32 b); i32 __stdcall i32osub(i32 a, i32 b); } // 32 bit unsigned and signed with overflow class ou32{ public: ou32* val(void){u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;} u32 ErrVal(void){R -1;} // value for error ou32() {v=0;} ou32(u32 a){v=a; } ou32(i32 a){v=(u32)(a<0? -1: a);} ou32(u8 a){v=a;} ou32(i8 a){v=(u32)(a<0? -1: a);} ou32(u16 a){v=a;} ou32(i16 a){v=(u32)(a<0? -1: a);} ou32& operator=(ou32& a){v=a.v; R *this;} ou32& operator=(u32 a){v=a; R *this;} ou32& operator=(i32 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator=(u16 a){v=a; R *this;} ou32& operator=(i16 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator=(u8 a){v=a; R *this;} ou32& operator=(i8 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator*=(ou32& a){v=u32omul(v, a.v); R *this;} ou32& operator+=(ou32& a){v=u32oadd(v, a.v); R *this;} ou32& operator-=(ou32& a){v=u32osub(v, a.v); R *this;} ou32& operator/=(ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1; else v=v/a.v; R *this; } ou32& operator++(){v=(v==-1? -1: ++v); R *this;} ou32& operator++(int) {ou32 *t; t=val(); *t=*this; if(v!=-1) ++v; R *t;} ou32& operator--(){v=(v==-1? -1: --v); R *this;} ou32& operator--(int) {ou32 *t; t=val(); *t=*this; if(v!=-1) --v; R *t;} friend ou32& operator*(ou32& a, ou32& b) {ou32 *r; r=a.val(); r->v=u32omul(a.v, b.v); R *r;} friend ou32& operator+(ou32& a, ou32& b) {ou32 *r; r=a.val(); r->v=u32oadd(a.v, b.v); R *r;} friend ou32& operator-(ou32& a, ou32& b) {ou32 *r; r=a.val(); r->v=u32osub(a.v, b.v); R *r;} friend ou32& operator/(ou32& a, ou32& b) {ou32 *r; r=a.val(); if(a.v==-1||b.v==-1||b.v==0) r->v=-1; else r->v=a.v/b.v; R *r; } friend ostream& operator<<(ostream& ostr, ou32& a) {if( a.v==-1 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;} friend i32 operator==(ou32& a, ou32& b){R a.v==b.v;} friend i32 operator!=(ou32& a, ou32& b){R a.v==b.v;} friend i32 operator<=(ou32& a, ou32& b){R a.v<=b.v;} friend i32 operator>=(ou32& a, ou32& b){R a.v>=b.v;} friend i32 operator<( ou32& a, ou32& b){R a.v< b.v;} friend i32 operator>( ou32& a, ou32& b){R a.v> b.v;} friend i32 operator==(ou32& a, u32 b){R a.v==b;} friend i32 operator!=(ou32& a, u32 b){R a.v==b;} friend i32 operator<=(ou32& a, u32 b){R a.v<=b;} friend i32 operator>=(ou32& a, u32 b){R a.v>=b;} friend i32 operator<( ou32& a, u32 b){R a.v< b;} friend i32 operator>( ou32& a, u32 b){R a.v> b;} u32 v; static u32 ic; static ou32 *maa; }; u32 ou32::ic=0; ou32 ma[64]; ou32* ou32::maa=ma; void fo(void) {u32 i, j, k; ou32 ui, uj, uk; // ou32 ui.v=ui.ErrVal(); // ui.v=-1 --ui.v; uj=ui+(ou32&)3u; // overflow + if(uj.v!=-1) P("ou32 error +\n"); ui=3u; uj=ui-(ou32)7u; // overflow - if(uj.v!=-1) P("ou32 error -\n"); ui=0xFFFFF; uj=ui*(u32)0xFFFF; // overflow * if(uj.v!=-1) P("ou32 error *\n"); ui=0xFFFFF; uj=ui/(u32)0; // overflow / if(uj.v!=-1) P("ou32 error / \n"); } int main(void) {if( sizeof(u32)!=4 || sizeof(u16)!=2 ) {P("Basic type error\n"); R 0;} fo(); R 0; } /* Error E2031 over.cpp 219: Cannot cast from 'unsigned int' to 'ou32 &' in function fo() Error E2093 over.cpp 223: 'operator-' not implemented in type 'ou32' for arguments of the same type in function fo() Error E2094 over.cpp 228: 'operator*' not implemented in type 'ou32' for arguments of type 'unsigned int' in function fo() Error E2094 over.cpp 232: 'operator/' not implemented in type 'ou32' for arguments of type 'unsigned int' in function fo() Warning W8008 over.cpp 237: Condition is always false in function main() Warning W8066 over.cpp 238: Unreachable code in function main() *** 4 errors in Compile *** Why not compile? in the book say that "ou32(u32 a){v=a; }" does the conversion from unsigned to ou32... or i read wrong? Is it possible define a conversion from unsigned[or type] to ou32 that use the circular array ma[64] [possible some cast function]? Thank you */ |
David Brown <david.brown@hesbynett.no>: Jun 02 10:45AM +0200 > [possible some cast function]? > Thank you > */ I /think/ the first error is because you asked to convert the u32 to a ou32&, while you only have a defined conversion to ou32. It makes no sense to cast to ou32& in fo(). However, if you try writing C++, rather than a mixture of assembly, toolchain-specific extensions, and complete gibberish, then it would be a lot easier to help you. |
asetofsymbols@gmail.com: Jun 02 03:15AM -0700 Just add some "const" and All ok this doing what I thought even if I not find where I wrote that... Thank you /* In one asm file compile for result .obj code section _DATA use32 public class=DATA global u32omul global u32oadd global u32osub global i32omul global i32oadd global i32osub section _BSS use32 public class=BSS section _TEXT use32 public class=CODE ;u32 __stdcall u32omul(u32 a, u32 b) ; 0ra, 4P_a, 8P_b align 4 u32omul: mov eax, dword[esp+ 4] cmp eax, -1 je .1 mov edx, dword[esp+ 8] cmp edx, -1 je .0 mul edx cmp edx, 0 je .1 .0: mov eax, -1 .1: ret 8 ;u32 __stdcall u32oadd(u32 a, u32 b) align 4 u32oadd: mov eax, dword[esp+ 4] mov edx, dword[esp+ 8] add eax, edx jnc .0 mov eax, -1 .0: ret 8 ;u32 __stdcall u32osub(u32 a, u32 b) align 4 u32osub: mov eax, dword[esp+ 4] cmp eax, -1 je .1 mov edx, dword[esp+ 8] cmp edx, -1 je .0 sub eax, edx jae .1 .0: mov eax, -1 .1: ret 8 ;i32 __stdcall i32omul(i32 a, i32 b) align 4 i32omul: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 imul edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 ;i32 __stdcall i32oadd(i32 a, i32 b) align 4 i32oadd: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 add eax, edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 ;i32 __stdcall i32osub(i32 a, i32 b) align 4 i32osub: mov eax, dword[esp+ 4] cmp eax, 0x80000000 je .1 mov edx, dword[esp+ 8] cmp edx, 0x80000000 je .0 sub eax, edx jno .1 .0: mov eax, 0x80000000 .1: ret 8 */ // bcc32 thisfile.cpp asmfile.obj #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <float.h> #include <limits.h> #include <iostream.h> #define G(a,b) if(a)goto b #define R return #define P printf #define M malloc #define Fr free #define F for #define S sizeof #define u8 unsigned char #define i8 signed char #define u16 unsigned short #define i16 signed short #define u32 unsigned #define i32 int #define d64 double // functions for detect u32 or i32 overflow in asm extern "C" { u32 __stdcall u32omul(u32 a, u32 b); u32 __stdcall u32oadd(u32 a, u32 b); u32 __stdcall u32osub(u32 a, u32 b); i32 __stdcall i32omul(i32 a, i32 b); i32 __stdcall i32oadd(i32 a, i32 b); i32 __stdcall i32osub(i32 a, i32 b); } // 32 bit unsigned and signed with overflow class ou32{ public: friend ou32* val(void) {u32 r=ic; ++ic; if(ic>=63) ic=0; R maa+r;} friend u32 ErrVal(void){R -1;} // value for error ou32() {v=0;} ou32(u32 a){v=a;} ou32(i32 a){v=(u32)(a<0? -1: a);} ou32(u8 a){v=a;} ou32(i8 a){v=(u32)(a<0? -1: a);} ou32(u16 a){v=a;} ou32(i16 a){v=(u32)(a<0? -1: a);} ou32(const ou32& a){v=a.v;} ou32& operator=(const ou32& a){v=a.v; R *this;} ou32& operator=(u32 a){v=a; R *this;} ou32& operator=(i32 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator=(u16 a){v=a; R *this;} ou32& operator=(i16 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator=(u8 a){v=a; R *this;} ou32& operator=(i8 a){v=(u32)(a<0? -1: a); R *this;} ou32& operator*=(const ou32& a){v=u32omul(v, a.v); R *this;} ou32& operator+=(const ou32& a){v=u32oadd(v, a.v); R *this;} ou32& operator-=(const ou32& a){v=u32osub(v, a.v); R *this;} ou32& operator/=(const ou32& a){if(v==-1||a.v==-1||a.v==0) v=-1; else v=v/a.v; R *this; } ou32& operator++(){v=(v==-1? -1: ++v); R *this;} ou32& operator++(int) {ou32 *t; t=val(); *t=*this; if(v!=-1) ++v; R *t;} ou32& operator--(){v=(v==-1? -1: --v); R *this;} ou32& operator--(int) {ou32 *t; t=val(); *t=*this; if(v!=-1) --v; R *t;} friend ou32& operator*(const ou32& a, const ou32& b) {ou32 *r; r=val(); r->v=u32omul(a.v, b.v); R *r;} friend ou32& operator+(const ou32& a, const ou32& b) {ou32 *r; r=val(); r->v=u32oadd(a.v, b.v); R *r;} friend ou32& operator-(const ou32& a, const ou32& b) {ou32 *r; r=val(); r->v=u32osub(a.v, b.v); R *r;} friend ou32& operator/(const ou32& a, const ou32& b) {ou32 *r; r=val(); if(a.v==-1||b.v==-1||b.v==0) r->v=-1; else r->v=a.v/b.v; R *r; } friend ostream& operator<<(ostream& ostr, ou32& a) {if( a.v==-1 ) ostr<<"ErrElm"; else ostr<<a.v; R ostr;} friend i32 operator==(const ou32& a, const ou32& b){R a.v==b.v;} friend i32 operator!=(const ou32& a, const ou32& b){R a.v==b.v;} friend i32 operator<=(const ou32& a, const ou32& b){R a.v<=b.v;} friend i32 operator>=(const ou32& a, const ou32& b){R a.v>=b.v;} friend i32 operator<( const ou32& a, const ou32& b){R a.v< b.v;} friend i32 operator>( const ou32& a, const ou32& b){R a.v> b.v;} u32 v; static u32 ic; static ou32 *maa; }; u32 ou32::ic=0; ou32 ma[64]; ou32* ou32::maa=ma; void fo(void) {u32 i, j, k; ou32 ui, uj, uk; // ou32 ui.v=ErrVal(); // ui.v=-1 --ui.v; uj=ui+3u; // overflow + if(uj.v!=-1) P("ou32 error +\n"); ui=3u; uj=ui-(ou32)7u; // overflow - if(uj.v!=-1) P("ou32 error -\n"); ui=0xFFFFF; uj=ui*(u32)0xFFFF; // overflow * if(uj.v!=-1) P("ou32 error *\n"); ui=0xFFFFF; uj=ui/(u32)0; // overflow / if(uj.v!=-1) P("ou32 error / \n"); P("If no print but only this: all ok\n"); } int main(void) {if( sizeof(u32)!=4 || sizeof(u16)!=2 ) {P("Basic type error\n"); R 0;} fo(); R 0; } /* ; ui.v=ErrVal(); // ui.v=-1 ; mov dword ptr [ebp-4],-1 ; ; --ui.v; ; dec dword ptr [ebp-4] ; ; uj=ui+3u; // overflow + ; mov dword ptr [ebp-16],3 mov eax,dword ptr [ebx] inc dword ptr [ebx] cmp dword ptr [ebx],63 jb short @2 xor edx,edx mov dword ptr [ebx],edx #sembra che converte 3u in ou32 utilizzando l'array tramite val() #inline [**come dovrebbe essere**] # ma io non ho fatto la conversione u32 a ou32 tramite val() #tutto automatico? @2: @3: mov esi,eax shl esi,2 add esi,dword ptr [@@ou32@maa] push dword ptr [ebp-16] push dword ptr [ebp-4] call @u32oadd mov dword ptr [esi],eax mov eax,esi mov edx,dword ptr [eax] mov dword ptr [edi],edx #chiama l'operatore + (ou32 ou32) anche esso inline... ok sembra ; ; if(uj.v!=-1) P("ou32 error +\n"); ; cmp dword ptr [edi],-1 je short @4 push offset s@ call @_printf pop ecx ; ; ; ui=3u; ; @4: mov dword ptr [ebp-4],3 ; ; uj=ui-(ou32)7u; // overflow - ; mov dword ptr [ebp-20],7 mov eax,dword ptr [ebx] inc dword ptr [ebx] cmp dword ptr [ebx],63 jb short @5 xor ecx,ecx mov dword ptr [ebx],ecx @5: @6: mov esi,eax shl esi,2 add esi,dword ptr [@@ou32@maa] push dword ptr [ebp-20] push dword ptr [ebp-4] call @u32osub mov dword ptr [esi],eax mov eax,esi mov edx,dword ptr [eax] mov dword ptr [edi],edx ; ; if(uj.v!=-1) P("ou32 error -\n"); ; cmp dword ptr [edi],-1 je short @7 push offset s@+14 call @_printf pop ecx ; ; ; ; ui=0xFFFFF; ; @7: mov dword ptr [ebp-4],1048575 ; ; uj=ui*(u32)0xFFFF; // overflow * ; mov dword ptr [ebp-24],65535 mov eax,dword ptr [ebx] inc dword ptr [ebx] cmp dword ptr [ebx],63 jb short @8 xor ecx,ecx mov dword ptr [ebx],ecx @8: @9: mov esi,eax shl esi,2 add esi,dword ptr [@@ou32@maa] push dword ptr [ebp-24] push dword ptr [ebp-4] call @u32omul mov dword ptr [esi],eax mov eax,esi mov edx,dword ptr [eax] mov dword ptr [edi],edx ; ; if(uj.v!=-1) P("ou32 error *\n"); ; cmp dword ptr [edi],-1 je short @10 push offset s@+28 call @_printf pop ecx ; ; ; ui=0xFFFFF; ; @10: mov dword ptr [ebp-4],1048575 ; ; uj=ui/(u32)0; // overflow / ; xor ecx,ecx mov dword ptr [ebp-28],ecx mov eax,dword ptr [ebx] inc dword ptr [ebx] cmp dword ptr [ebx],63 jb short @11 xor edx,edx mov dword ptr [ebx],edx @11: @12: mov ecx,eax shl ecx,2 add ecx,dword ptr [@@ou32@maa] cmp dword ptr [ebp-4],-1 je short @15 cmp dword ptr [ebp-28],-1 je short @15 cmp dword ptr [ebp-28],0 jne short @13 @15: mov dword ptr [ecx],-1 jmp short @14 @13: mov eax,dword ptr [ebp-4] xor edx,edx div dword ptr [ebp-28] mov dword ptr [ecx],eax @14: mov eax,ecx mov ecx,dword ptr [eax] mov dword ptr [edi],ecx ; ; if(uj.v!=-1) P("ou32 error / \n"); ; ?live16387@224: ; EDI = &uj cmp dword ptr [edi],-1 je short @16 push offset s@+42 call @_printf pop ecx ; ; ; P("If no print but only this: all ok\n"); ; ?live16387@240: ; @16: push offset s@+57 call @_printf pop ecx ; ; ; } ; */ |
red floyd <no.spam@its.invalid>: Jun 02 09:50AM -0700 > [redacted] What part of "x86 Assembly Language isn't C++" are you having trouble understanding? |
"Öö Tiib" <ootiib@hot.ee>: Jun 02 02:26PM -0700 On Tuesday, 2 June 2015 19:50:13 UTC+3, red floyd wrote: > > [redacted] > What part of "x86 Assembly Language isn't C++" are you having trouble > understanding? He is perhaps just joking. First asked why we do not discuss classes for safe and saturated numeric computing and then replies himself with assembler for processor of past millennia. |
asetofsymbols@gmail.com: Jun 02 04:29PM -0700 Red wrote:" What part of "x86 Assembly Language isn't C++" are you having trouble understanding?" I not understand const... For me the type& arguments in functions are all pointers but for my definition I not change them so they are as const ... If I want change one argument in a function I would use funt(T* arg) not funt(T& arg) Because in funt(&v) I can see it changes v when function is called For the remain C++ offer good solution to problems sometime using some little workaround in a little subset of C++ all I not see or use, and not want to see it is too much complex for me and perhaps for all you too |
Lane <software.research.development@gmail.com>: Jun 02 12:03AM -0500 I'm using a C api within the C++ MyClass. This works, but I'd like to be able to use the private fields (varX) within these callbacks. Is there anyway to make the callbacks look like class member functions? Currently, things look like the following. // file1.cpp void read_callback(Dev *dev, const MyData *t) { // do stuff ... } // file2.cpp class MyClass { private: Dev *dev; DevListener dl; // how to use these in the callback? int var1; long var2; string var3; double var4; public: MyClass(); ~MyClass(); void operator()() { try { dl.listener = read_callback; ret = Dev_addListener(dev, &dl); // ... ret = Dev_start_async_reads(dev); // ... } catch (const exception& e) { // exception } } }; |
"Lőrinczy Zsigmond" <nospam@for.me>: Jun 02 07:22AM +0200 On 2015.06.02. 7:03, Lane wrote: > I'm using a C api within the C++ MyClass. This works, but I'd like to be > able to use the private fields (varX) within these callbacks. Is there > anyway to make the callbacks look like class member functions? If the caller of the callback is passing a 'user-parameter' to the callback, then a static method might work: the user-parameter will be the address of the object. Example (with Hungarian comments): http://web.axelero.hu/lzsiga/cback.cc |
Paavo Helde <myfirstname@osa.pri.ee>: Jun 02 12:56AM -0500 Lane <software.research.development@gmail.com> wrote in news:mkjda812947 > I'm using a C api within the C++ MyClass. This works, but I'd like to be > able to use the private fields (varX) within these callbacks. Is there > anyway to make the callbacks look like class member functions? (1) You can declare callback functions as friends. (2) You can add public member functions to your class which are called by the callback functions. A bit more tedious, but clearer in the long run. The drawback with (2) is that these member functions are typically not really "public". A way to cope with that is to add comments like public: // implementation and use some naming schema like Foo_impl() in the method names to indicate these are not to be called willy-nilly. The static member function approach suggested by another poster is similar to (1), but a bit unportable (the static member function linkage may or may not be compatible with the C linkage assumed by the C API). To be fully portable one needs to use extern "C" callback functions with a C API, and (static) member functions cannot be declared extern "C". |
Cholo Lennon <chololennon@hotmail.com>: Jun 02 09:44AM -0300 On 06/02/2015 02:56 AM, Paavo Helde wrote: > not be compatible with the C linkage assumed by the C API). To be fully > portable one needs to use extern "C" callback functions with a C API, and > (static) member functions cannot be declared extern "C". Could you explain a bit more about portability problems? I've always used static member functions as C library callbacks... TIA -- Cholo Lennon Bs.As. ARG |
Martin Shobe <martin.shobe@yahoo.com>: Jun 02 08:57AM -0500 On 6/2/2015 7:44 AM, Cholo Lennon wrote: >> (static) member functions cannot be declared extern "C". > Could you explain a bit more about portability problems? I've always > used static member functions as C library callbacks... I don't know of any implementations that do this, but one could have an implementation that uses one calling convention, say everything on the stack, for extern "C" functions while the static member functions use a different one, say the first three in registers with the rest on the stack. This would cause problems when attempting to call the static member function from C library. For the example, the first three arguments would be whatever happened to be in those registers at the time of the call, the fourth parameter would contain the first parameter's data[1], etc. Martin Shobe [1] This isn't exactly right. We might have objects of different sizes that keep them from lining up so nicely. You should still get the idea of why it's not portable to use static member functions as C library callbacks. |
legalize+jeeves@mail.xmission.com (Richard): Jun 02 05:48PM [Please do not mail me a copy of your followup] Lane <software.research.development@gmail.com> spake the secret code >I'm using a C api within the C++ MyClass. This works, but I'd like to be >able to use the private fields (varX) within these callbacks. Is there >anyway to make the callbacks look like class member functions? C style callback APIs usually have a void* parameter named something like "user context" that is registered with the callback function. This opaque pointer value will be passed to the callback function when it is invoked. The typical adaptation of this to a C++ class is to have the class delcare a static method and register the static method as the callback with the 'this' pointer as the context argument. The static method casts the void* user context pointer back to the appropriate type and then immediately delegates to an instance method. The static method does not have to be declared extern "C" because noone is linking to it from a C source file; it is linked within a C++ source file. Example: ==== Makefile callback: callback.o main.o g++ -o callback $^ main.c: callback.h callback.cpp: callback.h ==== callback.h #if !defined(CALLBACK_H) #define CALLBACK_H typedef void callback_fn_t(void *context); #if defined(__cplusplus) extern "C" {
Subscribe to:
Post Comments (Atom)
|
No comments:
Post a Comment