Mercurial > pub > dyncall > dyncall
diff test/plain_c++/test_main.cc @ 0:3e629dc19168
initial from svn dyncall-1745
author | Daniel Adler |
---|---|
date | Thu, 19 Mar 2015 22:24:28 +0100 |
parents | |
children | e63089fe5bef |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/plain_c++/test_main.cc Thu Mar 19 22:24:28 2015 +0100 @@ -0,0 +1,293 @@ +/* + + Package: dyncall + Library: test + File: test/plain_c++/test_main.cc + Description: + License: + + Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>, + Tassilo Philipp <tphilipp@potion-studios.com> + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +*/ + + + + +#include "test_framework.h" +#include "../../dyncall/dyncall.h" +#include "../common/platformInit.h" +#include "../common/platformInit.c" /* Impl. for functions only used in this translation unit */ + + +/* ------------------------------------------------------------------------- + * test: identity function calls + * ------------------------------------------------------------------------- */ + +#define DEF_FUNCS(API,NAME) \ +void API fun_##NAME##_v() { } \ +DCbool API fun_##NAME##_b(DCbool x) { return x; } \ +DCint API fun_##NAME##_i(DCint x) { return x; } \ +DClong API fun_##NAME##_j(DClong x) { return x; } \ +DClonglong API fun_##NAME##_l(DClonglong x) { return x; } \ +DCfloat API fun_##NAME##_f(DCfloat x) { return x; } \ +DCdouble API fun_##NAME##_d(DCdouble x) { return x; } \ +DCpointer API fun_##NAME##_p(DCpointer x) { return x; } + +/* __cdecl */ + +#if !defined(DC__OS_Win32) +# define __declspec(X) +# define __cdecl +#endif + + +/* ------------------------------------------------------------------------- + * test: identity this calls + * ------------------------------------------------------------------------- */ + +union ValueUnion +{ + DCbool B; + DCint i; + DClong j; + DClonglong l; + DCfloat f; + DCdouble d; + DCpointer p; +}; + +/* C++ class using __cdecl this call */ + +// #define VTBI_DESTRUCTOR 0 + +/* + * the layout of the VTable is non-standard and it is not clear what is the initial real first method index. + * so for it turns out that: + * on vc/x86 : 1 + * on GCC/x86 : 2 + */ + +#if defined DC__C_MSVC +#define VTBI_BASE 1 +#else +#define VTBI_BASE 2 +#endif + +#define VTBI_SET_BOOL VTBI_BASE+0 +#define VTBI_GET_BOOL VTBI_BASE+1 +#define VTBI_SET_INT VTBI_BASE+2 +#define VTBI_GET_INT VTBI_BASE+3 +#define VTBI_SET_LONG VTBI_BASE+4 +#define VTBI_GET_LONG VTBI_BASE+5 +#define VTBI_SET_LONG_LONG VTBI_BASE+6 +#define VTBI_GET_LONG_LONG VTBI_BASE+7 +#define VTBI_SET_FLOAT VTBI_BASE+8 +#define VTBI_GET_FLOAT VTBI_BASE+9 +#define VTBI_SET_DOUBLE VTBI_BASE+10 +#define VTBI_GET_DOUBLE VTBI_BASE+11 +#define VTBI_SET_POINTER VTBI_BASE+12 +#define VTBI_GET_POINTER VTBI_BASE+13 + +class Value +{ +public: + virtual ~Value() {} + + virtual void __cdecl setBool(DCbool x) { mValue.B = x; } + virtual DCbool __cdecl getBool() { return mValue.B; } + virtual void __cdecl setInt(DCint x) { mValue.i = x; } + virtual DCint __cdecl getInt() { return mValue.i; } + virtual void __cdecl setLong(DClong x) { mValue.j = x; } + virtual DClong __cdecl getLong() { return mValue.j; } + virtual void __cdecl setLongLong(DClonglong x) { mValue.l = x; } + virtual DClonglong __cdecl getLongLong() { return mValue.l; } + virtual void __cdecl setFloat(DCfloat x) { mValue.f = x; } + virtual DCfloat __cdecl getFloat() { return mValue.f; } + virtual void __cdecl setDouble(DCdouble x) { mValue.d = x; } + virtual DCdouble __cdecl getDouble() { return mValue.d; } + virtual void __cdecl setPtr(DCpointer x) { mValue.p = x; } + virtual DCpointer __cdecl getPtr() { return mValue.p; } +private: + ValueUnion mValue; +}; + +/* C++ class using (on win32: microsoft) this call */ + +class ValueMS +{ +public: + virtual ~ValueMS() {} + + virtual void setBool(DCbool x) { mValue.B = x; } + virtual DCbool getBool() { return mValue.B; } + virtual void setInt(DCint x) { mValue.i = x; } + virtual DCint getInt() { return mValue.i; } + virtual void setLong(DClong x) { mValue.j = x; } + virtual DClong getLong() { return mValue.j; } + virtual void setLongLong(DClonglong x) { mValue.l = x; } + virtual DClonglong getLongLong() { return mValue.l; } + virtual void setFloat(DCfloat x) { mValue.f = x; } + virtual DCfloat getFloat() { return mValue.f; } + virtual void setDouble(DCdouble x) { mValue.d = x; } + virtual DCdouble getDouble() { return mValue.d; } + virtual void setPtr(DCpointer x) { mValue.p = x; } + virtual DCpointer getPtr() { return mValue.p; } +private: + ValueUnion mValue; +}; + +template<typename T> +void testCallValue(DCCallVM* pc) +{ + T o; + T* pThis = &o; + DCpointer* vtbl = *( (DCpointer**) pThis ); /* vtbl is located at beginning of class */ + + /* set/get bool (TRUE) */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgBool(pc,DC_TRUE); + dcCallVoid(pc, vtbl[VTBI_SET_BOOL] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallBool(pc, vtbl[VTBI_GET_BOOL] ) == DC_TRUE ); + /* set/get bool (FALSE) */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgBool(pc,DC_FALSE); + dcCallVoid(pc, vtbl[VTBI_SET_BOOL] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallBool(pc, vtbl[VTBI_GET_BOOL] ) == DC_FALSE ); + + /* set/get int */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgInt(pc,1234); + dcCallVoid(pc, vtbl[VTBI_SET_INT] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallInt(pc, vtbl[VTBI_GET_INT] ) == 1234 ); + + /* set/get long */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgLong(pc,0xCAFEBABEUL); + dcCallVoid(pc, vtbl[VTBI_SET_LONG] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallLong(pc, vtbl[VTBI_GET_LONG] ) == (DClong)0xCAFEBABEUL ); + + /* set/get long long */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgLongLong(pc,0xCAFEBABEDEADC0DELL); + dcCallVoid(pc, vtbl[VTBI_SET_LONG_LONG] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallLongLong(pc, vtbl[VTBI_GET_LONG_LONG] ) == (DClonglong)0xCAFEBABEDEADC0DELL ); + + /* set/get float */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgFloat(pc,1.2345f); + dcCallVoid(pc, vtbl[VTBI_SET_FLOAT] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallFloat(pc, vtbl[VTBI_GET_FLOAT] ) == 1.2345f ); + + /* set/get double */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgDouble(pc,1.23456789); + dcCallVoid(pc, vtbl[VTBI_SET_DOUBLE] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallDouble(pc, vtbl[VTBI_GET_DOUBLE] ) == 1.23456789 ); + + /* set/get pointer */ + + dcReset(pc); + dcArgPointer(pc, pThis); + dcArgPointer(pc, (DCpointer) 0xCAFEBABE ); + dcCallVoid(pc, vtbl[VTBI_SET_POINTER] ); + dcReset(pc); + dcArgPointer(pc, pThis); + DC_TEST( dcCallPointer(pc, vtbl[VTBI_GET_POINTER] ) == ( (DCpointer) 0xCAFEBABE ) ); +} + + +#ifdef DC__OS_Win32 + +DC_DEFINE_TEST_FUNC_BEGIN(testCallThisMS) + + DCCallVM* pc = dcNewCallVM(4096); + dcMode(pc,DC_CALL_C_X86_WIN32_THIS_MS); + dcReset(pc); + testCallValue<ValueMS>(pc); + dcFree(pc); + +DC_DEFINE_TEST_FUNC_END + +#endif + + +DC_DEFINE_TEST_FUNC_BEGIN(testCallThisC) + + DCCallVM* pc = dcNewCallVM(4096); + dcReset(pc); + testCallValue<Value>(pc); + dcFree(pc); + +DC_DEFINE_TEST_FUNC_END + + +extern "C" { + +int main(int argc, char* argv[]) +{ + dcTest_initPlatform(); + + int b = TRUE; + +#if defined(DC__OS_Win32) // ThisCall temporarily only for win 32 @@@ + + b = b && testCallThisC(); + printf("ThisC:%d\n",b); + +#if defined(DC__C_MSVC) + b = b && testCallThisMS(); + printf("ThisMS:%d\n",b); +#endif + +#endif + + printf("result: plain_cpp: %d\n", b); + + dcTest_deInitPlatform(); + + return !b; +} + +} // extern "C" +