From b11a83f1f408cf8c739c8af3830c4e89dbee6093 Mon Sep 17 00:00:00 2001 From: Martin Weismann Date: Wed, 12 Dec 2018 14:22:08 +0100 Subject: [PATCH] Versoin 1.2.4 --- .../Bindings/C/libprimes.h | 151 ++++ .../Bindings/C/libprimes_types.h | 83 ++ .../Bindings/CDynamic/libprimes_dynamic.cpp | 183 ++++ .../Bindings/CDynamic/libprimes_dynamic.h | 164 ++++ .../Bindings/CDynamic/libprimes_types.h | 83 ++ .../Bindings/Cpp/libprimes.cpp | 217 +++++ .../Bindings/Cpp/libprimes.h | 151 ++++ .../Bindings/Cpp/libprimes.hpp | 215 +++++ .../Bindings/Cpp/libprimes_types.h | 83 ++ .../Bindings/CppDynamic/libprimes_dynamic.h | 157 ++++ .../Bindings/CppDynamic/libprimes_dynamic.hpp | 513 ++++++++++++ .../Bindings/CppDynamic/libprimes_types.h | 83 ++ .../Bindings/Pascal/Unit_LibPrimes.pas | 598 +++++++++++++ .../Bindings/Python/LibPrimes.py | 231 +++++ .../Examples/Python/LibPrimes_Example.py | 15 +- .../Cpp/Stub/libprimes_sievecalculator.cpp | 5 +- .../Implementations/Pascal/.gitignore | 3 + .../Pascal/Interfaces/libprimes.lpr | 44 + .../Pascal/Interfaces/libprimes_exception.pas | 70 ++ .../Pascal/Interfaces/libprimes_exports.pas | 436 ++++++++++ .../Interfaces/libprimes_interfaces.pas | 75 ++ .../Pascal/Interfaces/libprimes_types.pas | 89 ++ .../Pascal/Stub/libprimes_impl.pas | 67 ++ .../Pascal/Stub/libprimes_impl_baseclass.pas | 27 + .../Pascal/Stub/libprimes_impl_calculator.pas | 60 ++ ...libprimes_impl_factorizationcalculator.pas | 102 +++ .../Stub/libprimes_impl_sievecalculator.pas | 98 +++ .../Implementations/Pascal/libprimes.lpi | 113 +++ Examples/Primes/Tutorial.md | 2 +- Examples/Primes/libPrimes.xml | 4 +- Examples/UnitTest/libUnitTest.xml | 8 +- README.md | 6 +- Source/automaticcomponenttoolkit.go | 15 +- Source/buildbindingcdynamic.go | 789 +++++++++--------- Source/buildbindingpascal.go | 673 ++------------- Source/buildimplementationcpp.go | 6 +- Source/buildimplementationpascal.go | 675 ++++++++++++--- Source/componentdefinition.go | 5 +- Source/languagec.go | 645 ++++++++++++++ Source/languagepascal.go | 609 ++++++++++++++ Source/languagewriter.go | 38 +- build.bat | 2 +- 42 files changed, 6458 insertions(+), 1135 deletions(-) create mode 100644 Examples/Primes/LibPrimes_component/Bindings/C/libprimes.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/C/libprimes_types.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.cpp create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_types.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.cpp create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.hpp create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes_types.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.hpp create mode 100644 Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_types.h create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Pascal/Unit_LibPrimes.pas create mode 100644 Examples/Primes/LibPrimes_component/Bindings/Python/LibPrimes.py create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/.gitignore create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes.lpr create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exception.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exports.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_interfaces.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_types.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_baseclass.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_calculator.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_factorizationcalculator.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_sievecalculator.pas create mode 100644 Examples/Primes/LibPrimes_component/Implementations/Pascal/libprimes.lpi create mode 100644 Source/languagec.go create mode 100644 Source/languagepascal.go diff --git a/Examples/Primes/LibPrimes_component/Bindings/C/libprimes.h b/Examples/Primes/LibPrimes_component/Bindings/C/libprimes.h new file mode 100644 index 00000000..bc0d2062 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/C/libprimes.h @@ -0,0 +1,151 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_HEADER +#define __LIBPRIMES_HEADER + +#ifdef __LIBPRIMES_DLL +#ifdef WIN32 +#define LIBPRIMES_DECLSPEC __declspec (dllexport) +#else // WIN32 +#define LIBPRIMES_DECLSPEC __attribute__((visibility("default"))) +#endif // WIN32 +#else // __LIBPRIMES_DLL +#define LIBPRIMES_DECLSPEC +#endif // __LIBPRIMES_DLL + +#include "libprimes_types.h" + +extern "C" { + +/************************************************************************************************************************* + Class definition for Calculator +**************************************************************************************************************************/ + +/** +* Returns the current value of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @param[out] pValue - The current value of this Calculator +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_getvalue (LibPrimes_Calculator pCalculator, unsigned long long * pValue); + +/** +* Sets the value to be factorized +* +* @param[in] pCalculator - Calculator instance. +* @param[in] nValue - The value to be factorized +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_setvalue (LibPrimes_Calculator pCalculator, unsigned long long nValue); + +/** +* Sets the progress callback function +* +* @param[in] pCalculator - Calculator instance. +* @param[in] pProgressCallback - The progress callback +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_setprogresscallback (LibPrimes_Calculator pCalculator, LibPrimesProgressCallback pProgressCallback); + +/** +* Performs the specific calculation of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_calculate (LibPrimes_Calculator pCalculator); + +/************************************************************************************************************************* + Class definition for FactorizationCalculator +**************************************************************************************************************************/ + +/** +* Returns the prime factors of this number (without multiplicity) +* +* @param[in] pFactorizationCalculator - FactorizationCalculator instance. +* @param[in] nPrimeFactorsBufferSize - Number of elements in buffer +* @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_factorizationcalculator_getprimefactors (LibPrimes_FactorizationCalculator pFactorizationCalculator, const unsigned int nPrimeFactorsBufferSize, unsigned int * pPrimeFactorsNeededCount, sLibPrimesPrimeFactor * pPrimeFactorsBuffer); + +/************************************************************************************************************************* + Class definition for SieveCalculator +**************************************************************************************************************************/ + +/** +* Returns all prime numbers lower or equal to the sieve's value +* +* @param[in] pSieveCalculator - SieveCalculator instance. +* @param[in] nPrimesBufferSize - Number of elements in buffer +* @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_sievecalculator_getprimes (LibPrimes_SieveCalculator pSieveCalculator, const unsigned int nPrimesBufferSize, unsigned int * pPrimesNeededCount, unsigned long long * pPrimesBuffer); + +/************************************************************************************************************************* + Global functions +**************************************************************************************************************************/ + +/** +* Creates a new FactorizationCalculator instance +* +* @param[out] pInstance - New FactorizationCalculator instance +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_createfactorizationcalculator (LibPrimes_FactorizationCalculator * pInstance); + +/** +* Creates a new SieveCalculator instance +* +* @param[out] pInstance - New SieveCalculator instance +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_createsievecalculator (LibPrimes_SieveCalculator * pInstance); + +/** +* Releases the memory of an Instance +* +* @param[in] pInstance - Instance Handle +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_releaseinstance (LibPrimes_BaseClass pInstance); + +/** +* retrieves the current version of the library. +* +* @param[out] pMajor - returns the major version of the library +* @param[out] pMinor - returns the minor version of the library +* @param[out] pMicro - returns the micro version of the library +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_getlibraryversion (unsigned int * pMajor, unsigned int * pMinor, unsigned int * pMicro); + +/** +* Handles Library Journaling +* +* @param[in] pFileName - Journal FileName +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_setjournal (const char * pFileName); + +} + +#endif // __LIBPRIMES_HEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/C/libprimes_types.h b/Examples/Primes/LibPrimes_component/Bindings/C/libprimes_types.h new file mode 100644 index 00000000..d00da88d --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/C/libprimes_types.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file with basic types in +order to allow an easy use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_TYPES_HEADER +#define __LIBPRIMES_TYPES_HEADER + +/************************************************************************************************************************* + General type definitions +**************************************************************************************************************************/ + +typedef int LibPrimesResult; +typedef void * LibPrimesHandle; + +/************************************************************************************************************************* + Version for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_VERSION_MAJOR 1 +#define LIBPRIMES_VERSION_MINOR 2 +#define LIBPRIMES_VERSION_MICRO 0 + +/************************************************************************************************************************* + Error constants for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_SUCCESS 0 +#define LIBPRIMES_ERROR_NOTIMPLEMENTED 1 +#define LIBPRIMES_ERROR_INVALIDPARAM 2 +#define LIBPRIMES_ERROR_INVALIDCAST 3 +#define LIBPRIMES_ERROR_BUFFERTOOSMALL 4 +#define LIBPRIMES_ERROR_GENERICEXCEPTION 5 +#define LIBPRIMES_ERROR_COULDNOTLOADLIBRARY 6 +#define LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT 7 +#define LIBPRIMES_ERROR_NORESULTAVAILABLE 8 +#define LIBPRIMES_ERROR_CALCULATIONABORTED 9 + +/************************************************************************************************************************* + Declaration of handle classes +**************************************************************************************************************************/ + +typedef LibPrimesHandle LibPrimes_BaseClass; +typedef LibPrimesHandle LibPrimes_Calculator; +typedef LibPrimesHandle LibPrimes_FactorizationCalculator; +typedef LibPrimesHandle LibPrimes_SieveCalculator; + +/************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************/ + +#pragma pack (1) + +typedef struct { + unsigned long long m_Prime; + unsigned int m_Multiplicity; +} sLibPrimesPrimeFactor; + +#pragma pack () + +/************************************************************************************************************************* + Declaration of function pointers +**************************************************************************************************************************/ + +/** +* LibPrimesProgressCallback - Callback to report calculation progress and query whether it should be aborted +* +* @param[in] fProgressPercentage - How far has the calculation progressed? +* @param[out] pShouldAbort - Should the calculation be aborted? +*/ +typedef void(*LibPrimesProgressCallback)(float, bool*); + +#endif // __LIBPRIMES_TYPES_HEADER diff --git a/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.cpp b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.cpp new file mode 100644 index 00000000..f36e6da7 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.cpp @@ -0,0 +1,183 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#include "libprimes_types.h" +#include "libprimes_dynamic.h" +#ifdef WIN32 +#include +#else // WIN32 +#include +#endif // WIN32 + +LibPrimesResult InitLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable) +{ + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + pWrapperTable->m_LibraryHandle = nullptr; + pWrapperTable->m_Calculator_GetValue = nullptr; + pWrapperTable->m_Calculator_SetValue = nullptr; + pWrapperTable->m_Calculator_SetProgressCallback = nullptr; + pWrapperTable->m_Calculator_Calculate = nullptr; + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = nullptr; + pWrapperTable->m_SieveCalculator_GetPrimes = nullptr; + pWrapperTable->m_CreateFactorizationCalculator = nullptr; + pWrapperTable->m_CreateSieveCalculator = nullptr; + pWrapperTable->m_ReleaseInstance = nullptr; + pWrapperTable->m_GetLibraryVersion = nullptr; + pWrapperTable->m_SetJournal = nullptr; + + return LIBPRIMES_SUCCESS; +} + +LibPrimesResult ReleaseLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable) +{ + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + if (pWrapperTable->m_LibraryHandle != nullptr) { + #ifdef WIN32 + HMODULE hModule = (HMODULE) pWrapperTable->m_LibraryHandle; + FreeLibrary (hModule); + #else // WIN32 + dlclose (pWrapperTable->m_LibraryHandle); + #endif // WIN32 + return InitLibPrimesWrapperTable (pWrapperTable); + } + + return LIBPRIMES_SUCCESS; +} + +LibPrimesResult LoadLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName) +{ + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + if (pLibraryFileName == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + #ifdef WIN32 + HMODULE hLibrary = LoadLibraryA (pLibraryFileName); + if (hLibrary == 0) + return LIBPRIMES_ERROR_COULDNOTLOADLIBRARY; + #else // WIN32 + void* hLibrary = dlopen (pLibraryFileName, RTLD_LAZY); + if (hLibrary == 0) + return LIBPRIMES_ERROR_COULDNOTLOADLIBRARY; + dlerror(); + #endif // WIN32 + + #ifdef WIN32 + pWrapperTable->m_Calculator_GetValue = (PLibPrimesCalculator_GetValuePtr) GetProcAddress (hLibrary, "libprimes_calculator_getvalue"); + #else // WIN32 + pWrapperTable->m_Calculator_GetValue = (PLibPrimesCalculator_GetValuePtr) dlsym (hLibrary, "libprimes_calculator_getvalue"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_GetValue == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_SetValue = (PLibPrimesCalculator_SetValuePtr) GetProcAddress (hLibrary, "libprimes_calculator_setvalue"); + #else // WIN32 + pWrapperTable->m_Calculator_SetValue = (PLibPrimesCalculator_SetValuePtr) dlsym (hLibrary, "libprimes_calculator_setvalue"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_SetValue == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_SetProgressCallback = (PLibPrimesCalculator_SetProgressCallbackPtr) GetProcAddress (hLibrary, "libprimes_calculator_setprogresscallback"); + #else // WIN32 + pWrapperTable->m_Calculator_SetProgressCallback = (PLibPrimesCalculator_SetProgressCallbackPtr) dlsym (hLibrary, "libprimes_calculator_setprogresscallback"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_SetProgressCallback == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_Calculate = (PLibPrimesCalculator_CalculatePtr) GetProcAddress (hLibrary, "libprimes_calculator_calculate"); + #else // WIN32 + pWrapperTable->m_Calculator_Calculate = (PLibPrimesCalculator_CalculatePtr) dlsym (hLibrary, "libprimes_calculator_calculate"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_Calculate == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = (PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) GetProcAddress (hLibrary, "libprimes_factorizationcalculator_getprimefactors"); + #else // WIN32 + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = (PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) dlsym (hLibrary, "libprimes_factorizationcalculator_getprimefactors"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_FactorizationCalculator_GetPrimeFactors == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_SieveCalculator_GetPrimes = (PLibPrimesSieveCalculator_GetPrimesPtr) GetProcAddress (hLibrary, "libprimes_sievecalculator_getprimes"); + #else // WIN32 + pWrapperTable->m_SieveCalculator_GetPrimes = (PLibPrimesSieveCalculator_GetPrimesPtr) dlsym (hLibrary, "libprimes_sievecalculator_getprimes"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_SieveCalculator_GetPrimes == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_CreateFactorizationCalculator = (PLibPrimesCreateFactorizationCalculatorPtr) GetProcAddress (hLibrary, "libprimes_createfactorizationcalculator"); + #else // WIN32 + pWrapperTable->m_CreateFactorizationCalculator = (PLibPrimesCreateFactorizationCalculatorPtr) dlsym (hLibrary, "libprimes_createfactorizationcalculator"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_CreateFactorizationCalculator == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_CreateSieveCalculator = (PLibPrimesCreateSieveCalculatorPtr) GetProcAddress (hLibrary, "libprimes_createsievecalculator"); + #else // WIN32 + pWrapperTable->m_CreateSieveCalculator = (PLibPrimesCreateSieveCalculatorPtr) dlsym (hLibrary, "libprimes_createsievecalculator"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_CreateSieveCalculator == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_ReleaseInstance = (PLibPrimesReleaseInstancePtr) GetProcAddress (hLibrary, "libprimes_releaseinstance"); + #else // WIN32 + pWrapperTable->m_ReleaseInstance = (PLibPrimesReleaseInstancePtr) dlsym (hLibrary, "libprimes_releaseinstance"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_ReleaseInstance == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_GetLibraryVersion = (PLibPrimesGetLibraryVersionPtr) GetProcAddress (hLibrary, "libprimes_getlibraryversion"); + #else // WIN32 + pWrapperTable->m_GetLibraryVersion = (PLibPrimesGetLibraryVersionPtr) dlsym (hLibrary, "libprimes_getlibraryversion"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_GetLibraryVersion == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_SetJournal = (PLibPrimesSetJournalPtr) GetProcAddress (hLibrary, "libprimes_setjournal"); + #else // WIN32 + pWrapperTable->m_SetJournal = (PLibPrimesSetJournalPtr) dlsym (hLibrary, "libprimes_setjournal"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_SetJournal == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + pWrapperTable->m_LibraryHandle = hLibrary; + return LIBPRIMES_SUCCESS; +} + diff --git a/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.h b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.h new file mode 100644 index 00000000..8c8d2128 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_dynamic.h @@ -0,0 +1,164 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_DYNAMICHEADER +#define __LIBPRIMES_DYNAMICHEADER + +#include "libprimes_types.h" + + +/************************************************************************************************************************* + Class definition for Calculator +**************************************************************************************************************************/ + +/** +* Returns the current value of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @param[out] pValue - The current value of this Calculator +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_GetValuePtr) (LibPrimes_Calculator pCalculator, unsigned long long * pValue); + +/** +* Sets the value to be factorized +* +* @param[in] pCalculator - Calculator instance. +* @param[in] nValue - The value to be factorized +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_SetValuePtr) (LibPrimes_Calculator pCalculator, unsigned long long nValue); + +/** +* Sets the progress callback function +* +* @param[in] pCalculator - Calculator instance. +* @param[in] pProgressCallback - The progress callback +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_SetProgressCallbackPtr) (LibPrimes_Calculator pCalculator, LibPrimesProgressCallback pProgressCallback); + +/** +* Performs the specific calculation of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_CalculatePtr) (LibPrimes_Calculator pCalculator); + +/************************************************************************************************************************* + Class definition for FactorizationCalculator +**************************************************************************************************************************/ + +/** +* Returns the prime factors of this number (without multiplicity) +* +* @param[in] pFactorizationCalculator - FactorizationCalculator instance. +* @param[in] nPrimeFactorsBufferSize - Number of elements in buffer +* @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) (LibPrimes_FactorizationCalculator pFactorizationCalculator, const unsigned int nPrimeFactorsBufferSize, unsigned int * pPrimeFactorsNeededCount, sLibPrimesPrimeFactor * pPrimeFactorsBuffer); + +/************************************************************************************************************************* + Class definition for SieveCalculator +**************************************************************************************************************************/ + +/** +* Returns all prime numbers lower or equal to the sieve's value +* +* @param[in] pSieveCalculator - SieveCalculator instance. +* @param[in] nPrimesBufferSize - Number of elements in buffer +* @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesSieveCalculator_GetPrimesPtr) (LibPrimes_SieveCalculator pSieveCalculator, const unsigned int nPrimesBufferSize, unsigned int * pPrimesNeededCount, unsigned long long * pPrimesBuffer); + +/************************************************************************************************************************* + Global functions +**************************************************************************************************************************/ + +/** +* Creates a new FactorizationCalculator instance +* +* @param[out] pInstance - New FactorizationCalculator instance +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCreateFactorizationCalculatorPtr) (LibPrimes_FactorizationCalculator * pInstance); + +/** +* Creates a new SieveCalculator instance +* +* @param[out] pInstance - New SieveCalculator instance +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCreateSieveCalculatorPtr) (LibPrimes_SieveCalculator * pInstance); + +/** +* Releases the memory of an Instance +* +* @param[in] pInstance - Instance Handle +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesReleaseInstancePtr) (LibPrimes_BaseClass pInstance); + +/** +* retrieves the current version of the library. +* +* @param[out] pMajor - returns the major version of the library +* @param[out] pMinor - returns the minor version of the library +* @param[out] pMicro - returns the micro version of the library +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesGetLibraryVersionPtr) (unsigned int * pMajor, unsigned int * pMinor, unsigned int * pMicro); + +/** +* Handles Library Journaling +* +* @param[in] pFileName - Journal FileName +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesSetJournalPtr) (const char * pFileName); + +/************************************************************************************************************************* + Function Table Structure +**************************************************************************************************************************/ + +typedef struct { + void * m_LibraryHandle; + PLibPrimesCalculator_GetValuePtr m_Calculator_GetValue; + PLibPrimesCalculator_SetValuePtr m_Calculator_SetValue; + PLibPrimesCalculator_SetProgressCallbackPtr m_Calculator_SetProgressCallback; + PLibPrimesCalculator_CalculatePtr m_Calculator_Calculate; + PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr m_FactorizationCalculator_GetPrimeFactors; + PLibPrimesSieveCalculator_GetPrimesPtr m_SieveCalculator_GetPrimes; + PLibPrimesCreateFactorizationCalculatorPtr m_CreateFactorizationCalculator; + PLibPrimesCreateSieveCalculatorPtr m_CreateSieveCalculator; + PLibPrimesReleaseInstancePtr m_ReleaseInstance; + PLibPrimesGetLibraryVersionPtr m_GetLibraryVersion; + PLibPrimesSetJournalPtr m_SetJournal; +} sLibPrimesDynamicWrapperTable; + +/************************************************************************************************************************* + Load DLL dynamically +**************************************************************************************************************************/ +LibPrimesResult InitLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable); +LibPrimesResult ReleaseLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable); +LibPrimesResult LoadLibPrimesWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName); + +#endif // __LIBPRIMES_DYNAMICHEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_types.h b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_types.h new file mode 100644 index 00000000..d00da88d --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CDynamic/libprimes_types.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file with basic types in +order to allow an easy use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_TYPES_HEADER +#define __LIBPRIMES_TYPES_HEADER + +/************************************************************************************************************************* + General type definitions +**************************************************************************************************************************/ + +typedef int LibPrimesResult; +typedef void * LibPrimesHandle; + +/************************************************************************************************************************* + Version for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_VERSION_MAJOR 1 +#define LIBPRIMES_VERSION_MINOR 2 +#define LIBPRIMES_VERSION_MICRO 0 + +/************************************************************************************************************************* + Error constants for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_SUCCESS 0 +#define LIBPRIMES_ERROR_NOTIMPLEMENTED 1 +#define LIBPRIMES_ERROR_INVALIDPARAM 2 +#define LIBPRIMES_ERROR_INVALIDCAST 3 +#define LIBPRIMES_ERROR_BUFFERTOOSMALL 4 +#define LIBPRIMES_ERROR_GENERICEXCEPTION 5 +#define LIBPRIMES_ERROR_COULDNOTLOADLIBRARY 6 +#define LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT 7 +#define LIBPRIMES_ERROR_NORESULTAVAILABLE 8 +#define LIBPRIMES_ERROR_CALCULATIONABORTED 9 + +/************************************************************************************************************************* + Declaration of handle classes +**************************************************************************************************************************/ + +typedef LibPrimesHandle LibPrimes_BaseClass; +typedef LibPrimesHandle LibPrimes_Calculator; +typedef LibPrimesHandle LibPrimes_FactorizationCalculator; +typedef LibPrimesHandle LibPrimes_SieveCalculator; + +/************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************/ + +#pragma pack (1) + +typedef struct { + unsigned long long m_Prime; + unsigned int m_Multiplicity; +} sLibPrimesPrimeFactor; + +#pragma pack () + +/************************************************************************************************************************* + Declaration of function pointers +**************************************************************************************************************************/ + +/** +* LibPrimesProgressCallback - Callback to report calculation progress and query whether it should be aborted +* +* @param[in] fProgressPercentage - How far has the calculation progressed? +* @param[out] pShouldAbort - Should the calculation be aborted? +*/ +typedef void(*LibPrimesProgressCallback)(float, bool*); + +#endif // __LIBPRIMES_TYPES_HEADER diff --git a/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.cpp b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.cpp new file mode 100644 index 00000000..d248a72a --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.cpp @@ -0,0 +1,217 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated C++ Wrapper Implementation file in order to allow +an easy use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#include "libprimes.hpp" + +#include + +namespace LibPrimes { + +/************************************************************************************************************************* + Class ELibPrimesException +**************************************************************************************************************************/ + ELibPrimesException::ELibPrimesException(LibPrimesResult errorcode) + : std::runtime_error ("LibPrimes Error " + std::to_string (errorcode)) + { + m_errorcode = errorcode; + } + + LibPrimesResult ELibPrimesException::getErrorCode () + { + return m_errorcode; + } + +/************************************************************************************************************************* + Class CLibPrimesBaseClass +**************************************************************************************************************************/ + + CLibPrimesBaseClass::CLibPrimesBaseClass(LibPrimesHandle pHandle) + { + m_pHandle = pHandle; + } + + CLibPrimesBaseClass::~CLibPrimesBaseClass() + { + CLibPrimesWrapper::ReleaseInstance(this); + } + + void CLibPrimesBaseClass::CheckError(LibPrimesResult nResult) + { + CLibPrimesWrapper::CheckError(m_pHandle, nResult); + } + + LibPrimesHandle CLibPrimesBaseClass::GetHandle() + { + return m_pHandle; + } + + +/************************************************************************************************************************* + Class CLibPrimesCalculator +**************************************************************************************************************************/ + /** + * CLibPrimesCalculator::CLibPrimesCalculator - Constructor for Calculator class. + */ + CLibPrimesCalculator::CLibPrimesCalculator (LibPrimesHandle pHandle) + : CLibPrimesBaseClass (pHandle) + { } + + /** + * CLibPrimesCalculator::GetValue - Returns the current value of this Calculator + * @return The current value of this Calculator + */ + unsigned long long CLibPrimesCalculator::GetValue () + { + unsigned long long resultValue = 0; + CheckError ( libprimes_calculator_getvalue (m_pHandle, &resultValue) ); + return resultValue; + } + + /** + * CLibPrimesCalculator::SetValue - Sets the value to be factorized + * @param[in] nValue - The value to be factorized + */ + void CLibPrimesCalculator::SetValue (const unsigned long long nValue) + { + CheckError ( libprimes_calculator_setvalue (m_pHandle, nValue) ); + } + + /** + * CLibPrimesCalculator::SetProgressCallback - Sets the progress callback function + * @param[in] pProgressCallback - The progress callback + */ + void CLibPrimesCalculator::SetProgressCallback (const LibPrimesProgressCallback pProgressCallback) + { + CheckError ( libprimes_calculator_setprogresscallback (m_pHandle, pProgressCallback) ); + } + + /** + * CLibPrimesCalculator::Calculate - Performs the specific calculation of this Calculator + */ + void CLibPrimesCalculator::Calculate () + { + CheckError ( libprimes_calculator_calculate (m_pHandle) ); + } + +/************************************************************************************************************************* + Class CLibPrimesFactorizationCalculator +**************************************************************************************************************************/ + /** + * CLibPrimesFactorizationCalculator::CLibPrimesFactorizationCalculator - Constructor for FactorizationCalculator class. + */ + CLibPrimesFactorizationCalculator::CLibPrimesFactorizationCalculator (LibPrimesHandle pHandle) + : CLibPrimesCalculator (pHandle) + { } + + /** + * CLibPrimesFactorizationCalculator::GetPrimeFactors - Returns the prime factors of this number (without multiplicity) + * @param[out] PrimeFactorsBuffer - The prime factors of this number + */ + void CLibPrimesFactorizationCalculator::GetPrimeFactors (std::vector & PrimeFactorsBuffer) + { + unsigned int elementsNeededPrimeFactors = 0; + unsigned int elementsWrittenPrimeFactors = 0; + CheckError ( libprimes_factorizationcalculator_getprimefactors (m_pHandle, 0, &elementsNeededPrimeFactors, nullptr) ); + PrimeFactorsBuffer.resize(elementsNeededPrimeFactors); + CheckError ( libprimes_factorizationcalculator_getprimefactors (m_pHandle, elementsNeededPrimeFactors, &elementsWrittenPrimeFactors, PrimeFactorsBuffer.data()) ); + } + +/************************************************************************************************************************* + Class CLibPrimesSieveCalculator +**************************************************************************************************************************/ + /** + * CLibPrimesSieveCalculator::CLibPrimesSieveCalculator - Constructor for SieveCalculator class. + */ + CLibPrimesSieveCalculator::CLibPrimesSieveCalculator (LibPrimesHandle pHandle) + : CLibPrimesCalculator (pHandle) + { } + + /** + * CLibPrimesSieveCalculator::GetPrimes - Returns all prime numbers lower or equal to the sieve's value + * @param[out] PrimesBuffer - The primes lower or equal to the sieve's value + */ + void CLibPrimesSieveCalculator::GetPrimes (std::vector & PrimesBuffer) + { + unsigned int elementsNeededPrimes = 0; + unsigned int elementsWrittenPrimes = 0; + CheckError ( libprimes_sievecalculator_getprimes (m_pHandle, 0, &elementsNeededPrimes, nullptr) ); + PrimesBuffer.resize(elementsNeededPrimes); + CheckError ( libprimes_sievecalculator_getprimes (m_pHandle, elementsNeededPrimes, &elementsWrittenPrimes, PrimesBuffer.data()) ); + } + + /** + * CLibPrimesWrapper::CreateFactorizationCalculator - Creates a new FactorizationCalculator instance + * @return New FactorizationCalculator instance + */ + PLibPrimesFactorizationCalculator CLibPrimesWrapper::CreateFactorizationCalculator () + { + LibPrimesHandle hInstance = nullptr; + CheckError (nullptr, libprimes_createfactorizationcalculator (&hInstance) ); + return std::make_shared (hInstance); + } + + /** + * CLibPrimesWrapper::CreateSieveCalculator - Creates a new SieveCalculator instance + * @return New SieveCalculator instance + */ + PLibPrimesSieveCalculator CLibPrimesWrapper::CreateSieveCalculator () + { + LibPrimesHandle hInstance = nullptr; + CheckError (nullptr, libprimes_createsievecalculator (&hInstance) ); + return std::make_shared (hInstance); + } + + /** + * CLibPrimesWrapper::ReleaseInstance - Releases the memory of an Instance + * @param[in] pInstance - Instance Handle + */ + void CLibPrimesWrapper::ReleaseInstance (CLibPrimesBaseClass * pInstance) + { + LibPrimesHandle hInstance = nullptr; + if (pInstance != nullptr) { + hInstance = pInstance->GetHandle (); + }; + CheckError (nullptr, libprimes_releaseinstance (hInstance) ); + } + + /** + * CLibPrimesWrapper::GetLibraryVersion - retrieves the current version of the library. + * @param[out] nMajor - returns the major version of the library + * @param[out] nMinor - returns the minor version of the library + * @param[out] nMicro - returns the micro version of the library + */ + void CLibPrimesWrapper::GetLibraryVersion (unsigned int & nMajor, unsigned int & nMinor, unsigned int & nMicro) + { + CheckError (nullptr, libprimes_getlibraryversion (&nMajor, &nMinor, &nMicro) ); + } + + /** + * CLibPrimesWrapper::SetJournal - Handles Library Journaling + * @param[in] sFileName - Journal FileName + */ + void CLibPrimesWrapper::SetJournal (const std::string & sFileName) + { + CheckError (nullptr, libprimes_setjournal (sFileName.c_str()) ); + } + + void CLibPrimesWrapper::CheckError(LibPrimesHandle handle, LibPrimesResult nResult) + { + if (nResult != 0) + throw ELibPrimesException (nResult); + } + + +}; + diff --git a/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.h b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.h new file mode 100644 index 00000000..bc0d2062 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.h @@ -0,0 +1,151 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_HEADER +#define __LIBPRIMES_HEADER + +#ifdef __LIBPRIMES_DLL +#ifdef WIN32 +#define LIBPRIMES_DECLSPEC __declspec (dllexport) +#else // WIN32 +#define LIBPRIMES_DECLSPEC __attribute__((visibility("default"))) +#endif // WIN32 +#else // __LIBPRIMES_DLL +#define LIBPRIMES_DECLSPEC +#endif // __LIBPRIMES_DLL + +#include "libprimes_types.h" + +extern "C" { + +/************************************************************************************************************************* + Class definition for Calculator +**************************************************************************************************************************/ + +/** +* Returns the current value of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @param[out] pValue - The current value of this Calculator +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_getvalue (LibPrimes_Calculator pCalculator, unsigned long long * pValue); + +/** +* Sets the value to be factorized +* +* @param[in] pCalculator - Calculator instance. +* @param[in] nValue - The value to be factorized +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_setvalue (LibPrimes_Calculator pCalculator, unsigned long long nValue); + +/** +* Sets the progress callback function +* +* @param[in] pCalculator - Calculator instance. +* @param[in] pProgressCallback - The progress callback +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_setprogresscallback (LibPrimes_Calculator pCalculator, LibPrimesProgressCallback pProgressCallback); + +/** +* Performs the specific calculation of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_calculator_calculate (LibPrimes_Calculator pCalculator); + +/************************************************************************************************************************* + Class definition for FactorizationCalculator +**************************************************************************************************************************/ + +/** +* Returns the prime factors of this number (without multiplicity) +* +* @param[in] pFactorizationCalculator - FactorizationCalculator instance. +* @param[in] nPrimeFactorsBufferSize - Number of elements in buffer +* @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_factorizationcalculator_getprimefactors (LibPrimes_FactorizationCalculator pFactorizationCalculator, const unsigned int nPrimeFactorsBufferSize, unsigned int * pPrimeFactorsNeededCount, sLibPrimesPrimeFactor * pPrimeFactorsBuffer); + +/************************************************************************************************************************* + Class definition for SieveCalculator +**************************************************************************************************************************/ + +/** +* Returns all prime numbers lower or equal to the sieve's value +* +* @param[in] pSieveCalculator - SieveCalculator instance. +* @param[in] nPrimesBufferSize - Number of elements in buffer +* @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_sievecalculator_getprimes (LibPrimes_SieveCalculator pSieveCalculator, const unsigned int nPrimesBufferSize, unsigned int * pPrimesNeededCount, unsigned long long * pPrimesBuffer); + +/************************************************************************************************************************* + Global functions +**************************************************************************************************************************/ + +/** +* Creates a new FactorizationCalculator instance +* +* @param[out] pInstance - New FactorizationCalculator instance +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_createfactorizationcalculator (LibPrimes_FactorizationCalculator * pInstance); + +/** +* Creates a new SieveCalculator instance +* +* @param[out] pInstance - New SieveCalculator instance +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_createsievecalculator (LibPrimes_SieveCalculator * pInstance); + +/** +* Releases the memory of an Instance +* +* @param[in] pInstance - Instance Handle +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_releaseinstance (LibPrimes_BaseClass pInstance); + +/** +* retrieves the current version of the library. +* +* @param[out] pMajor - returns the major version of the library +* @param[out] pMinor - returns the minor version of the library +* @param[out] pMicro - returns the micro version of the library +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_getlibraryversion (unsigned int * pMajor, unsigned int * pMinor, unsigned int * pMicro); + +/** +* Handles Library Journaling +* +* @param[in] pFileName - Journal FileName +* @return error code or 0 (success) +*/ +LIBPRIMES_DECLSPEC LibPrimesResult libprimes_setjournal (const char * pFileName); + +} + +#endif // __LIBPRIMES_HEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.hpp b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.hpp new file mode 100644 index 00000000..2990d6e5 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes.hpp @@ -0,0 +1,215 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated C++ Header file in order to allow an easy use + of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + + +#ifndef __LIBPRIMES_CPPHEADER +#define __LIBPRIMES_CPPHEADER + +#include "libprimes.h" +#include +#include +#include +#include + +namespace LibPrimes { + +/************************************************************************************************************************* + Forward Declaration of all classes +**************************************************************************************************************************/ + +class CLibPrimesBaseClass; +class CLibPrimesCalculator; +class CLibPrimesFactorizationCalculator; +class CLibPrimesSieveCalculator; + +/************************************************************************************************************************* + Declaration of shared pointer types +**************************************************************************************************************************/ + +typedef std::shared_ptr PLibPrimesBaseClass; +typedef std::shared_ptr PLibPrimesCalculator; +typedef std::shared_ptr PLibPrimesFactorizationCalculator; +typedef std::shared_ptr PLibPrimesSieveCalculator; + +/************************************************************************************************************************* + Class ELibPrimesException +**************************************************************************************************************************/ +class ELibPrimesException : public std::runtime_error { + protected: + /** + * Error code for the Exception. + */ + LibPrimesResult m_errorcode; + + public: + /** + * Exception Constructor. + */ + ELibPrimesException (LibPrimesResult errorcode); + + /** + * Returns error code + */ + LibPrimesResult getErrorCode (); + +}; + +/************************************************************************************************************************* + Class CLibPrimesBaseClass +**************************************************************************************************************************/ +class CLibPrimesBaseClass { + protected: + /* Handle to Instance in library*/ + LibPrimesHandle m_pHandle; + + /* Checks for an Error code and raises Exceptions */ + void CheckError(LibPrimesResult nResult); + public: + + /** + * CLibPrimesBaseClass::CLibPrimesBaseClass - Constructor for Base class. + */ + CLibPrimesBaseClass(LibPrimesHandle pHandle); + + /** + * CLibPrimesBaseClass::~CLibPrimesBaseClass - Destructor for Base class. + */ + virtual ~CLibPrimesBaseClass(); + + /** + * CLibPrimesBaseClass::GetHandle - Returns handle to instance. + */ + LibPrimesHandle GetHandle(); +}; + +/************************************************************************************************************************* + Class CLibPrimesCalculator +**************************************************************************************************************************/ +class CLibPrimesCalculator : public CLibPrimesBaseClass { + public: + + /** + * CLibPrimesCalculator::CLibPrimesCalculator - Constructor for Calculator class. + */ + CLibPrimesCalculator (LibPrimesHandle pHandle); + + /** + * CLibPrimesCalculator::GetValue - Returns the current value of this Calculator + * @return The current value of this Calculator + */ + unsigned long long GetValue (); + + /** + * CLibPrimesCalculator::SetValue - Sets the value to be factorized + * @param[in] nValue - The value to be factorized + */ + void SetValue (const unsigned long long nValue); + + /** + * CLibPrimesCalculator::SetProgressCallback - Sets the progress callback function + * @param[in] pProgressCallback - The progress callback + */ + void SetProgressCallback (const LibPrimesProgressCallback pProgressCallback); + + /** + * CLibPrimesCalculator::Calculate - Performs the specific calculation of this Calculator + */ + void Calculate (); +}; + + +/************************************************************************************************************************* + Class CLibPrimesFactorizationCalculator +**************************************************************************************************************************/ +class CLibPrimesFactorizationCalculator : public CLibPrimesCalculator { + public: + + /** + * CLibPrimesFactorizationCalculator::CLibPrimesFactorizationCalculator - Constructor for FactorizationCalculator class. + */ + CLibPrimesFactorizationCalculator (LibPrimesHandle pHandle); + + /** + * CLibPrimesFactorizationCalculator::GetPrimeFactors - Returns the prime factors of this number (without multiplicity) + * @param[out] PrimeFactorsBuffer - The prime factors of this number + */ + void GetPrimeFactors (std::vector & PrimeFactorsBuffer); +}; + + +/************************************************************************************************************************* + Class CLibPrimesSieveCalculator +**************************************************************************************************************************/ +class CLibPrimesSieveCalculator : public CLibPrimesCalculator { + public: + + /** + * CLibPrimesSieveCalculator::CLibPrimesSieveCalculator - Constructor for SieveCalculator class. + */ + CLibPrimesSieveCalculator (LibPrimesHandle pHandle); + + /** + * CLibPrimesSieveCalculator::GetPrimes - Returns all prime numbers lower or equal to the sieve's value + * @param[out] PrimesBuffer - The primes lower or equal to the sieve's value + */ + void GetPrimes (std::vector & PrimesBuffer); +}; + + +/************************************************************************************************************************* + Class CLibPrimesWrapper +**************************************************************************************************************************/ +class CLibPrimesWrapper { +public: + static void CheckError(LibPrimesHandle handle, LibPrimesResult nResult); + + /** + * CLibPrimesWrapper::CreateFactorizationCalculator - Creates a new FactorizationCalculator instance + * @return New FactorizationCalculator instance + */ + static PLibPrimesFactorizationCalculator CreateFactorizationCalculator (); + + /** + * CLibPrimesWrapper::CreateSieveCalculator - Creates a new SieveCalculator instance + * @return New SieveCalculator instance + */ + static PLibPrimesSieveCalculator CreateSieveCalculator (); + + /** + * CLibPrimesWrapper::ReleaseInstance - Releases the memory of an Instance + * @param[in] pInstance - Instance Handle + */ + static void ReleaseInstance (CLibPrimesBaseClass * pInstance); + + /** + * CLibPrimesWrapper::GetLibraryVersion - retrieves the current version of the library. + * @param[out] nMajor - returns the major version of the library + * @param[out] nMinor - returns the minor version of the library + * @param[out] nMicro - returns the micro version of the library + */ + static void GetLibraryVersion (unsigned int & nMajor, unsigned int & nMinor, unsigned int & nMicro); + + /** + * CLibPrimesWrapper::SetJournal - Handles Library Journaling + * @param[in] sFileName - Journal FileName + */ + static void SetJournal (const std::string & sFileName); +}; + + +}; + +#endif // __LIBPRIMES_CPPHEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes_types.h b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes_types.h new file mode 100644 index 00000000..d00da88d --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Cpp/libprimes_types.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file with basic types in +order to allow an easy use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_TYPES_HEADER +#define __LIBPRIMES_TYPES_HEADER + +/************************************************************************************************************************* + General type definitions +**************************************************************************************************************************/ + +typedef int LibPrimesResult; +typedef void * LibPrimesHandle; + +/************************************************************************************************************************* + Version for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_VERSION_MAJOR 1 +#define LIBPRIMES_VERSION_MINOR 2 +#define LIBPRIMES_VERSION_MICRO 0 + +/************************************************************************************************************************* + Error constants for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_SUCCESS 0 +#define LIBPRIMES_ERROR_NOTIMPLEMENTED 1 +#define LIBPRIMES_ERROR_INVALIDPARAM 2 +#define LIBPRIMES_ERROR_INVALIDCAST 3 +#define LIBPRIMES_ERROR_BUFFERTOOSMALL 4 +#define LIBPRIMES_ERROR_GENERICEXCEPTION 5 +#define LIBPRIMES_ERROR_COULDNOTLOADLIBRARY 6 +#define LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT 7 +#define LIBPRIMES_ERROR_NORESULTAVAILABLE 8 +#define LIBPRIMES_ERROR_CALCULATIONABORTED 9 + +/************************************************************************************************************************* + Declaration of handle classes +**************************************************************************************************************************/ + +typedef LibPrimesHandle LibPrimes_BaseClass; +typedef LibPrimesHandle LibPrimes_Calculator; +typedef LibPrimesHandle LibPrimes_FactorizationCalculator; +typedef LibPrimesHandle LibPrimes_SieveCalculator; + +/************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************/ + +#pragma pack (1) + +typedef struct { + unsigned long long m_Prime; + unsigned int m_Multiplicity; +} sLibPrimesPrimeFactor; + +#pragma pack () + +/************************************************************************************************************************* + Declaration of function pointers +**************************************************************************************************************************/ + +/** +* LibPrimesProgressCallback - Callback to report calculation progress and query whether it should be aborted +* +* @param[in] fProgressPercentage - How far has the calculation progressed? +* @param[out] pShouldAbort - Should the calculation be aborted? +*/ +typedef void(*LibPrimesProgressCallback)(float, bool*); + +#endif // __LIBPRIMES_TYPES_HEADER diff --git a/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.h b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.h new file mode 100644 index 00000000..d2712cb8 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.h @@ -0,0 +1,157 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_DYNAMICHEADER +#define __LIBPRIMES_DYNAMICHEADER + +#include "libprimes_types.h" + + +/************************************************************************************************************************* + Class definition for Calculator +**************************************************************************************************************************/ + +/** +* Returns the current value of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @param[out] pValue - The current value of this Calculator +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_GetValuePtr) (LibPrimes_Calculator pCalculator, unsigned long long * pValue); + +/** +* Sets the value to be factorized +* +* @param[in] pCalculator - Calculator instance. +* @param[in] nValue - The value to be factorized +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_SetValuePtr) (LibPrimes_Calculator pCalculator, unsigned long long nValue); + +/** +* Sets the progress callback function +* +* @param[in] pCalculator - Calculator instance. +* @param[in] pProgressCallback - The progress callback +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_SetProgressCallbackPtr) (LibPrimes_Calculator pCalculator, LibPrimesProgressCallback pProgressCallback); + +/** +* Performs the specific calculation of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCalculator_CalculatePtr) (LibPrimes_Calculator pCalculator); + +/************************************************************************************************************************* + Class definition for FactorizationCalculator +**************************************************************************************************************************/ + +/** +* Returns the prime factors of this number (without multiplicity) +* +* @param[in] pFactorizationCalculator - FactorizationCalculator instance. +* @param[in] nPrimeFactorsBufferSize - Number of elements in buffer +* @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) (LibPrimes_FactorizationCalculator pFactorizationCalculator, const unsigned int nPrimeFactorsBufferSize, unsigned int * pPrimeFactorsNeededCount, sLibPrimesPrimeFactor * pPrimeFactorsBuffer); + +/************************************************************************************************************************* + Class definition for SieveCalculator +**************************************************************************************************************************/ + +/** +* Returns all prime numbers lower or equal to the sieve's value +* +* @param[in] pSieveCalculator - SieveCalculator instance. +* @param[in] nPrimesBufferSize - Number of elements in buffer +* @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesSieveCalculator_GetPrimesPtr) (LibPrimes_SieveCalculator pSieveCalculator, const unsigned int nPrimesBufferSize, unsigned int * pPrimesNeededCount, unsigned long long * pPrimesBuffer); + +/************************************************************************************************************************* + Global functions +**************************************************************************************************************************/ + +/** +* Creates a new FactorizationCalculator instance +* +* @param[out] pInstance - New FactorizationCalculator instance +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCreateFactorizationCalculatorPtr) (LibPrimes_FactorizationCalculator * pInstance); + +/** +* Creates a new SieveCalculator instance +* +* @param[out] pInstance - New SieveCalculator instance +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesCreateSieveCalculatorPtr) (LibPrimes_SieveCalculator * pInstance); + +/** +* Releases the memory of an Instance +* +* @param[in] pInstance - Instance Handle +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesReleaseInstancePtr) (LibPrimes_BaseClass pInstance); + +/** +* retrieves the current version of the library. +* +* @param[out] pMajor - returns the major version of the library +* @param[out] pMinor - returns the minor version of the library +* @param[out] pMicro - returns the micro version of the library +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesGetLibraryVersionPtr) (unsigned int * pMajor, unsigned int * pMinor, unsigned int * pMicro); + +/** +* Handles Library Journaling +* +* @param[in] pFileName - Journal FileName +* @return error code or 0 (success) +*/ +typedef LibPrimesResult (*PLibPrimesSetJournalPtr) (const char * pFileName); + +/************************************************************************************************************************* + Function Table Structure +**************************************************************************************************************************/ + +typedef struct { + void * m_LibraryHandle; + PLibPrimesCalculator_GetValuePtr m_Calculator_GetValue; + PLibPrimesCalculator_SetValuePtr m_Calculator_SetValue; + PLibPrimesCalculator_SetProgressCallbackPtr m_Calculator_SetProgressCallback; + PLibPrimesCalculator_CalculatePtr m_Calculator_Calculate; + PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr m_FactorizationCalculator_GetPrimeFactors; + PLibPrimesSieveCalculator_GetPrimesPtr m_SieveCalculator_GetPrimes; + PLibPrimesCreateFactorizationCalculatorPtr m_CreateFactorizationCalculator; + PLibPrimesCreateSieveCalculatorPtr m_CreateSieveCalculator; + PLibPrimesReleaseInstancePtr m_ReleaseInstance; + PLibPrimesGetLibraryVersionPtr m_GetLibraryVersion; + PLibPrimesSetJournalPtr m_SetJournal; +} sLibPrimesDynamicWrapperTable; + +#endif // __LIBPRIMES_DYNAMICHEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.hpp b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.hpp new file mode 100644 index 00000000..26392e10 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_dynamic.hpp @@ -0,0 +1,513 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated C++ Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_DYNAMICCPPHEADER +#define __LIBPRIMES_DYNAMICCPPHEADER + +#include "libprimes_types.h" +#include "libprimes_dynamic.h" + +#ifdef WIN32 +#include +#else // WIN32 +#include +#endif // WIN32 +#include +#include +#include +#include + +namespace LibPrimes { + +/************************************************************************************************************************* + Forward Declaration of all classes +**************************************************************************************************************************/ + +class CLibPrimesBaseClass; +class CLibPrimesWrapper; +class CLibPrimesCalculator; +class CLibPrimesFactorizationCalculator; +class CLibPrimesSieveCalculator; + +/************************************************************************************************************************* + Declaration of shared pointer types +**************************************************************************************************************************/ + +typedef std::shared_ptr PLibPrimesBaseClass; +typedef std::shared_ptr PLibPrimesWrapper; +typedef std::shared_ptr PLibPrimesCalculator; +typedef std::shared_ptr PLibPrimesFactorizationCalculator; +typedef std::shared_ptr PLibPrimesSieveCalculator; + +/************************************************************************************************************************* + Class ELibPrimesException +**************************************************************************************************************************/ +class ELibPrimesException : public std::runtime_error { +protected: + /** + * Error code for the Exception. + */ + LibPrimesResult m_errorcode; + +public: + /** + * Exception Constructor. + */ + ELibPrimesException (LibPrimesResult errorcode) + : std::runtime_error ("LibPrimes Error " + std::to_string (errorcode)) + { + m_errorcode = errorcode; + } + + /** + * Returns error code + */ + LibPrimesResult getErrorCode () + { + return m_errorcode; + } + +}; + +/************************************************************************************************************************* + Class CLibPrimesWrapper +**************************************************************************************************************************/ +class CLibPrimesWrapper { +public: + + CLibPrimesWrapper (const std::string &sFileName) + { + CheckError (nullptr, initWrapperTable (&m_WrapperTable)); + CheckError (nullptr, loadWrapperTable (&m_WrapperTable, sFileName.c_str ())); + } + + static PLibPrimesWrapper loadLibrary (const std::string &sFileName) + { + return std::make_shared (sFileName); + } + + ~CLibPrimesWrapper () + { + releaseWrapperTable (&m_WrapperTable); + } + + void CheckError(LibPrimesHandle handle, LibPrimesResult nResult) + { + if (nResult != 0) + throw ELibPrimesException (nResult); + } + + + PLibPrimesFactorizationCalculator CreateFactorizationCalculator (); + PLibPrimesSieveCalculator CreateSieveCalculator (); + void ReleaseInstance (CLibPrimesBaseClass * pInstance); + void GetLibraryVersion (unsigned int & nMajor, unsigned int & nMinor, unsigned int & nMicro); + void SetJournal (const std::string & sFileName); + +private: + sLibPrimesDynamicWrapperTable m_WrapperTable; + + LibPrimesResult initWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable); + LibPrimesResult releaseWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable); + LibPrimesResult loadWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName); + + friend class CLibPrimesCalculator; + friend class CLibPrimesFactorizationCalculator; + friend class CLibPrimesSieveCalculator; + +}; + +/************************************************************************************************************************* + Class CLibPrimesBaseClass +**************************************************************************************************************************/ +class CLibPrimesBaseClass { +protected: + /* Wrapper Object that created the class..*/ + CLibPrimesWrapper * m_pWrapper; + /* Handle to Instance in library*/ + LibPrimesHandle m_pHandle; + + /* Checks for an Error code and raises Exceptions */ + void CheckError(LibPrimesResult nResult) + { + if (m_pWrapper != nullptr) + m_pWrapper->CheckError (m_pHandle, nResult); + } + +public: + + /** + * CLibPrimesBaseClass::CLibPrimesBaseClass - Constructor for Base class. + */ + CLibPrimesBaseClass(CLibPrimesWrapper * pWrapper, LibPrimesHandle pHandle) + : m_pWrapper (pWrapper), m_pHandle (pHandle) + { + } + + /** + * CLibPrimesBaseClass::~CLibPrimesBaseClass - Destructor for Base class. + */ + virtual ~CLibPrimesBaseClass() + { + if (m_pWrapper != nullptr) + m_pWrapper->ReleaseInstance (this); + m_pWrapper = nullptr; + } + + /** + * CLibPrimesBaseClass::GetHandle - Returns handle to instance. + */ + LibPrimesHandle GetHandle() + { + return m_pHandle; + } +}; + + +/************************************************************************************************************************* + Class CLibPrimesCalculator +**************************************************************************************************************************/ +class CLibPrimesCalculator : public CLibPrimesBaseClass { +public: + + /** + * CLibPrimesCalculator::CLibPrimesCalculator - Constructor for Calculator class. + */ + CLibPrimesCalculator (CLibPrimesWrapper * pWrapper, LibPrimesHandle pHandle) + : CLibPrimesBaseClass (pWrapper, pHandle) + { + } + + + /** + * CLibPrimesCalculator::GetValue - Returns the current value of this Calculator + * @return The current value of this Calculator + */ + unsigned long long GetValue () + { + unsigned long long resultValue = 0; + + CheckError ( m_pWrapper->m_WrapperTable.m_Calculator_GetValue (m_pHandle, &resultValue) ); + return resultValue; + } + + /** + * CLibPrimesCalculator::SetValue - Sets the value to be factorized + * @param[in] nValue - The value to be factorized + */ + void SetValue (const unsigned long long nValue) + { + CheckError ( m_pWrapper->m_WrapperTable.m_Calculator_SetValue (m_pHandle, nValue) ); + } + + /** + * CLibPrimesCalculator::SetProgressCallback - Sets the progress callback function + * @param[in] pProgressCallback - The progress callback + */ + void SetProgressCallback (const LibPrimesProgressCallback pProgressCallback) + { + CheckError ( m_pWrapper->m_WrapperTable.m_Calculator_SetProgressCallback (m_pHandle, pProgressCallback) ); + } + + /** + * CLibPrimesCalculator::Calculate - Performs the specific calculation of this Calculator + */ + void Calculate () + { + CheckError ( m_pWrapper->m_WrapperTable.m_Calculator_Calculate (m_pHandle) ); + } +}; + + +/************************************************************************************************************************* + Class CLibPrimesFactorizationCalculator +**************************************************************************************************************************/ +class CLibPrimesFactorizationCalculator : public CLibPrimesCalculator { +public: + + /** + * CLibPrimesFactorizationCalculator::CLibPrimesFactorizationCalculator - Constructor for FactorizationCalculator class. + */ + CLibPrimesFactorizationCalculator (CLibPrimesWrapper * pWrapper, LibPrimesHandle pHandle) + : CLibPrimesCalculator (pWrapper, pHandle) + { + } + + + /** + * CLibPrimesFactorizationCalculator::GetPrimeFactors - Returns the prime factors of this number (without multiplicity) + * @param[out] PrimeFactorsBuffer - The prime factors of this number + */ + void GetPrimeFactors (std::vector & PrimeFactorsBuffer) + { + unsigned int elementsNeededPrimeFactors = 0; + unsigned int elementsWrittenPrimeFactors = 0; + CheckError ( m_pWrapper->m_WrapperTable.m_FactorizationCalculator_GetPrimeFactors (m_pHandle, 0, &elementsNeededPrimeFactors, nullptr) ); + PrimeFactorsBuffer.resize(elementsNeededPrimeFactors); + CheckError ( m_pWrapper->m_WrapperTable.m_FactorizationCalculator_GetPrimeFactors (m_pHandle, elementsNeededPrimeFactors, &elementsWrittenPrimeFactors, PrimeFactorsBuffer.data()) ); + } +}; + + +/************************************************************************************************************************* + Class CLibPrimesSieveCalculator +**************************************************************************************************************************/ +class CLibPrimesSieveCalculator : public CLibPrimesCalculator { +public: + + /** + * CLibPrimesSieveCalculator::CLibPrimesSieveCalculator - Constructor for SieveCalculator class. + */ + CLibPrimesSieveCalculator (CLibPrimesWrapper * pWrapper, LibPrimesHandle pHandle) + : CLibPrimesCalculator (pWrapper, pHandle) + { + } + + + /** + * CLibPrimesSieveCalculator::GetPrimes - Returns all prime numbers lower or equal to the sieve's value + * @param[out] PrimesBuffer - The primes lower or equal to the sieve's value + */ + void GetPrimes (std::vector & PrimesBuffer) + { + unsigned int elementsNeededPrimes = 0; + unsigned int elementsWrittenPrimes = 0; + CheckError ( m_pWrapper->m_WrapperTable.m_SieveCalculator_GetPrimes (m_pHandle, 0, &elementsNeededPrimes, nullptr) ); + PrimesBuffer.resize(elementsNeededPrimes); + CheckError ( m_pWrapper->m_WrapperTable.m_SieveCalculator_GetPrimes (m_pHandle, elementsNeededPrimes, &elementsWrittenPrimes, PrimesBuffer.data()) ); + } +}; + + + /** + * CLibPrimesWrapper::CreateFactorizationCalculator - Creates a new FactorizationCalculator instance + * @return New FactorizationCalculator instance + */ + inline PLibPrimesFactorizationCalculator CLibPrimesWrapper::CreateFactorizationCalculator () + { + LibPrimesHandle hInstance = nullptr; + CheckError (nullptr, m_WrapperTable.m_CreateFactorizationCalculator (&hInstance) ); + return std::make_shared (this, hInstance); + } + + /** + * CLibPrimesWrapper::CreateSieveCalculator - Creates a new SieveCalculator instance + * @return New SieveCalculator instance + */ + inline PLibPrimesSieveCalculator CLibPrimesWrapper::CreateSieveCalculator () + { + LibPrimesHandle hInstance = nullptr; + CheckError (nullptr, m_WrapperTable.m_CreateSieveCalculator (&hInstance) ); + return std::make_shared (this, hInstance); + } + + /** + * CLibPrimesWrapper::ReleaseInstance - Releases the memory of an Instance + * @param[in] pInstance - Instance Handle + */ + inline void CLibPrimesWrapper::ReleaseInstance (CLibPrimesBaseClass * pInstance) + { + LibPrimesHandle hInstance = nullptr; + if (pInstance != nullptr) { + hInstance = pInstance->GetHandle (); + }; + + CheckError (nullptr, m_WrapperTable.m_ReleaseInstance (hInstance) ); + } + + /** + * CLibPrimesWrapper::GetLibraryVersion - retrieves the current version of the library. + * @param[out] nMajor - returns the major version of the library + * @param[out] nMinor - returns the minor version of the library + * @param[out] nMicro - returns the micro version of the library + */ + inline void CLibPrimesWrapper::GetLibraryVersion (unsigned int & nMajor, unsigned int & nMinor, unsigned int & nMicro) + { + CheckError (nullptr, m_WrapperTable.m_GetLibraryVersion (&nMajor, &nMinor, &nMicro) ); + } + + /** + * CLibPrimesWrapper::SetJournal - Handles Library Journaling + * @param[in] sFileName - Journal FileName + */ + inline void CLibPrimesWrapper::SetJournal (const std::string & sFileName) + { + CheckError (nullptr, m_WrapperTable.m_SetJournal (sFileName.c_str()) ); + } + + inline LibPrimesResult CLibPrimesWrapper::initWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable) + { + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + pWrapperTable->m_LibraryHandle = nullptr; + pWrapperTable->m_Calculator_GetValue = nullptr; + pWrapperTable->m_Calculator_SetValue = nullptr; + pWrapperTable->m_Calculator_SetProgressCallback = nullptr; + pWrapperTable->m_Calculator_Calculate = nullptr; + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = nullptr; + pWrapperTable->m_SieveCalculator_GetPrimes = nullptr; + pWrapperTable->m_CreateFactorizationCalculator = nullptr; + pWrapperTable->m_CreateSieveCalculator = nullptr; + pWrapperTable->m_ReleaseInstance = nullptr; + pWrapperTable->m_GetLibraryVersion = nullptr; + pWrapperTable->m_SetJournal = nullptr; + + return LIBPRIMES_SUCCESS; + } + + inline LibPrimesResult CLibPrimesWrapper::releaseWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable) + { + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + if (pWrapperTable->m_LibraryHandle != nullptr) { + #ifdef WIN32 + HMODULE hModule = (HMODULE) pWrapperTable->m_LibraryHandle; + FreeLibrary (hModule); + #else // WIN32 + dlclose (pWrapperTable->m_LibraryHandle); + #endif // WIN32 + return initWrapperTable (pWrapperTable); + } + + return LIBPRIMES_SUCCESS; + } + + inline LibPrimesResult CLibPrimesWrapper::loadWrapperTable (sLibPrimesDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName) + { + if (pWrapperTable == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + if (pLibraryFileName == nullptr) + return LIBPRIMES_ERROR_INVALIDPARAM; + + #ifdef WIN32 + HMODULE hLibrary = LoadLibraryA (pLibraryFileName); + if (hLibrary == 0) + return LIBPRIMES_ERROR_COULDNOTLOADLIBRARY; + #else // WIN32 + void* hLibrary = dlopen (pLibraryFileName, RTLD_LAZY); + if (hLibrary == 0) + return LIBPRIMES_ERROR_COULDNOTLOADLIBRARY; + dlerror(); + #endif // WIN32 + + #ifdef WIN32 + pWrapperTable->m_Calculator_GetValue = (PLibPrimesCalculator_GetValuePtr) GetProcAddress (hLibrary, "libprimes_calculator_getvalue"); + #else // WIN32 + pWrapperTable->m_Calculator_GetValue = (PLibPrimesCalculator_GetValuePtr) dlsym (hLibrary, "libprimes_calculator_getvalue"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_GetValue == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_SetValue = (PLibPrimesCalculator_SetValuePtr) GetProcAddress (hLibrary, "libprimes_calculator_setvalue"); + #else // WIN32 + pWrapperTable->m_Calculator_SetValue = (PLibPrimesCalculator_SetValuePtr) dlsym (hLibrary, "libprimes_calculator_setvalue"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_SetValue == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_SetProgressCallback = (PLibPrimesCalculator_SetProgressCallbackPtr) GetProcAddress (hLibrary, "libprimes_calculator_setprogresscallback"); + #else // WIN32 + pWrapperTable->m_Calculator_SetProgressCallback = (PLibPrimesCalculator_SetProgressCallbackPtr) dlsym (hLibrary, "libprimes_calculator_setprogresscallback"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_SetProgressCallback == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_Calculator_Calculate = (PLibPrimesCalculator_CalculatePtr) GetProcAddress (hLibrary, "libprimes_calculator_calculate"); + #else // WIN32 + pWrapperTable->m_Calculator_Calculate = (PLibPrimesCalculator_CalculatePtr) dlsym (hLibrary, "libprimes_calculator_calculate"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_Calculator_Calculate == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = (PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) GetProcAddress (hLibrary, "libprimes_factorizationcalculator_getprimefactors"); + #else // WIN32 + pWrapperTable->m_FactorizationCalculator_GetPrimeFactors = (PLibPrimesFactorizationCalculator_GetPrimeFactorsPtr) dlsym (hLibrary, "libprimes_factorizationcalculator_getprimefactors"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_FactorizationCalculator_GetPrimeFactors == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_SieveCalculator_GetPrimes = (PLibPrimesSieveCalculator_GetPrimesPtr) GetProcAddress (hLibrary, "libprimes_sievecalculator_getprimes"); + #else // WIN32 + pWrapperTable->m_SieveCalculator_GetPrimes = (PLibPrimesSieveCalculator_GetPrimesPtr) dlsym (hLibrary, "libprimes_sievecalculator_getprimes"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_SieveCalculator_GetPrimes == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_CreateFactorizationCalculator = (PLibPrimesCreateFactorizationCalculatorPtr) GetProcAddress (hLibrary, "libprimes_createfactorizationcalculator"); + #else // WIN32 + pWrapperTable->m_CreateFactorizationCalculator = (PLibPrimesCreateFactorizationCalculatorPtr) dlsym (hLibrary, "libprimes_createfactorizationcalculator"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_CreateFactorizationCalculator == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_CreateSieveCalculator = (PLibPrimesCreateSieveCalculatorPtr) GetProcAddress (hLibrary, "libprimes_createsievecalculator"); + #else // WIN32 + pWrapperTable->m_CreateSieveCalculator = (PLibPrimesCreateSieveCalculatorPtr) dlsym (hLibrary, "libprimes_createsievecalculator"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_CreateSieveCalculator == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_ReleaseInstance = (PLibPrimesReleaseInstancePtr) GetProcAddress (hLibrary, "libprimes_releaseinstance"); + #else // WIN32 + pWrapperTable->m_ReleaseInstance = (PLibPrimesReleaseInstancePtr) dlsym (hLibrary, "libprimes_releaseinstance"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_ReleaseInstance == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_GetLibraryVersion = (PLibPrimesGetLibraryVersionPtr) GetProcAddress (hLibrary, "libprimes_getlibraryversion"); + #else // WIN32 + pWrapperTable->m_GetLibraryVersion = (PLibPrimesGetLibraryVersionPtr) dlsym (hLibrary, "libprimes_getlibraryversion"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_GetLibraryVersion == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + #ifdef WIN32 + pWrapperTable->m_SetJournal = (PLibPrimesSetJournalPtr) GetProcAddress (hLibrary, "libprimes_setjournal"); + #else // WIN32 + pWrapperTable->m_SetJournal = (PLibPrimesSetJournalPtr) dlsym (hLibrary, "libprimes_setjournal"); + dlerror(); + #endif // WIN32 + if (pWrapperTable->m_SetJournal == nullptr) + return LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT; + + pWrapperTable->m_LibraryHandle = hLibrary; + return LIBPRIMES_SUCCESS; + } + +} // namespace LibPrimes + +#endif // __LIBPRIMES_DYNAMICCPPHEADER + diff --git a/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_types.h b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_types.h new file mode 100644 index 00000000..d00da88d --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/CppDynamic/libprimes_types.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated plain C Header file with basic types in +order to allow an easy use of Prime Numbers Interface + +Interface version: 1.2.0 + +*/ + +#ifndef __LIBPRIMES_TYPES_HEADER +#define __LIBPRIMES_TYPES_HEADER + +/************************************************************************************************************************* + General type definitions +**************************************************************************************************************************/ + +typedef int LibPrimesResult; +typedef void * LibPrimesHandle; + +/************************************************************************************************************************* + Version for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_VERSION_MAJOR 1 +#define LIBPRIMES_VERSION_MINOR 2 +#define LIBPRIMES_VERSION_MICRO 0 + +/************************************************************************************************************************* + Error constants for LibPrimes +**************************************************************************************************************************/ + +#define LIBPRIMES_SUCCESS 0 +#define LIBPRIMES_ERROR_NOTIMPLEMENTED 1 +#define LIBPRIMES_ERROR_INVALIDPARAM 2 +#define LIBPRIMES_ERROR_INVALIDCAST 3 +#define LIBPRIMES_ERROR_BUFFERTOOSMALL 4 +#define LIBPRIMES_ERROR_GENERICEXCEPTION 5 +#define LIBPRIMES_ERROR_COULDNOTLOADLIBRARY 6 +#define LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT 7 +#define LIBPRIMES_ERROR_NORESULTAVAILABLE 8 +#define LIBPRIMES_ERROR_CALCULATIONABORTED 9 + +/************************************************************************************************************************* + Declaration of handle classes +**************************************************************************************************************************/ + +typedef LibPrimesHandle LibPrimes_BaseClass; +typedef LibPrimesHandle LibPrimes_Calculator; +typedef LibPrimesHandle LibPrimes_FactorizationCalculator; +typedef LibPrimesHandle LibPrimes_SieveCalculator; + +/************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************/ + +#pragma pack (1) + +typedef struct { + unsigned long long m_Prime; + unsigned int m_Multiplicity; +} sLibPrimesPrimeFactor; + +#pragma pack () + +/************************************************************************************************************************* + Declaration of function pointers +**************************************************************************************************************************/ + +/** +* LibPrimesProgressCallback - Callback to report calculation progress and query whether it should be aborted +* +* @param[in] fProgressPercentage - How far has the calculation progressed? +* @param[out] pShouldAbort - Should the calculation be aborted? +*/ +typedef void(*LibPrimesProgressCallback)(float, bool*); + +#endif // __LIBPRIMES_TYPES_HEADER diff --git a/Examples/Primes/LibPrimes_component/Bindings/Pascal/Unit_LibPrimes.pas b/Examples/Primes/LibPrimes_component/Bindings/Pascal/Unit_LibPrimes.pas new file mode 100644 index 00000000..d9a01ebf --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Pascal/Unit_LibPrimes.pas @@ -0,0 +1,598 @@ +{$IFDEF FPC}{$MODE DELPHI}{$ENDIF} +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal Header file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +*) + +unit Unit_LibPrimes; + +interface + +uses + {$IFDEF WINDOWS} + Windows, + {$ELSE} + dynlibs, + {$ENDIF} + Types, + Classes, + SysUtils; + +(************************************************************************************************************************* + Version definition for LibPrimes +**************************************************************************************************************************) + +const + LIBPRIMES_VERSION_MAJOR = 1; + LIBPRIMES_VERSION_MINOR = 2; + LIBPRIMES_VERSION_MICRO = 0; + + +(************************************************************************************************************************* + General type definitions +**************************************************************************************************************************) + +type + TLibPrimesResult = Cardinal; + TLibPrimesHandle = Pointer; + + PLibPrimesResult = ^TLibPrimesResult; + PLibPrimesHandle = ^TLibPrimesHandle; + +(************************************************************************************************************************* + Error Constants for LibPrimes +**************************************************************************************************************************) + +const + LIBPRIMES_SUCCESS = 0; + LIBPRIMES_ERROR_NOTIMPLEMENTED = 1; + LIBPRIMES_ERROR_INVALIDPARAM = 2; + LIBPRIMES_ERROR_INVALIDCAST = 3; + LIBPRIMES_ERROR_BUFFERTOOSMALL = 4; + LIBPRIMES_ERROR_GENERICEXCEPTION = 5; + LIBPRIMES_ERROR_COULDNOTLOADLIBRARY = 6; + LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT = 7; + LIBPRIMES_ERROR_NORESULTAVAILABLE = 8; + LIBPRIMES_ERROR_CALCULATIONABORTED = 9; + +(************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************) + +type + + PLibPrimesPrimeFactor = ^TLibPrimesPrimeFactor; + TLibPrimesPrimeFactor = packed record + FPrime: QWord; + FMultiplicity: Cardinal; + end; + + +(************************************************************************************************************************* + Declaration of function types +**************************************************************************************************************************) + + PLibPrimes_ProgressCallback = function(const fProgressPercentage: Single; out pShouldAbort: Cardinal): Integer; + +(************************************************************************************************************************* + Declaration of struct arrays +**************************************************************************************************************************) + + ArrayOfLibPrimesPrimeFactor = array of TLibPrimesPrimeFactor; + +(************************************************************************************************************************* + Declaration of handle classes +**************************************************************************************************************************) + +type + TLibPrimesBaseClass = class; + TLibPrimesWrapper = class; + TLibPrimesCalculator = class; + TLibPrimesFactorizationCalculator = class; + TLibPrimesSieveCalculator = class; + + +(************************************************************************************************************************* + Function type definitions for Calculator +**************************************************************************************************************************) + + (** + * Returns the current value of this Calculator + * + * @param[in] pCalculator - Calculator instance. + * @param[out] pValue - The current value of this Calculator + * @return error code or 0 (success) + *) + TLibPrimesCalculator_GetValueFunc = function (pCalculator: TLibPrimesHandle; out pValue: QWord): TLibPrimesResult; cdecl; + + (** + * Sets the value to be factorized + * + * @param[in] pCalculator - Calculator instance. + * @param[in] nValue - The value to be factorized + * @return error code or 0 (success) + *) + TLibPrimesCalculator_SetValueFunc = function (pCalculator: TLibPrimesHandle; const nValue: QWord): TLibPrimesResult; cdecl; + + (** + * Sets the progress callback function + * + * @param[in] pCalculator - Calculator instance. + * @param[in] pProgressCallback - The progress callback + * @return error code or 0 (success) + *) + TLibPrimesCalculator_SetProgressCallbackFunc = function (pCalculator: TLibPrimesHandle; const pProgressCallback: PLibPrimes_ProgressCallback): TLibPrimesResult; cdecl; + + (** + * Performs the specific calculation of this Calculator + * + * @param[in] pCalculator - Calculator instance. + * @return error code or 0 (success) + *) + TLibPrimesCalculator_CalculateFunc = function (pCalculator: TLibPrimesHandle): TLibPrimesResult; cdecl; + + +(************************************************************************************************************************* + Function type definitions for FactorizationCalculator +**************************************************************************************************************************) + + (** + * Returns the prime factors of this number (without multiplicity) + * + * @param[in] pFactorizationCalculator - FactorizationCalculator instance. + * @param[in] nPrimeFactorsCount - Number of elements in buffer + * @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. + * @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number + * @return error code or 0 (success) + *) + TLibPrimesFactorizationCalculator_GetPrimeFactorsFunc = function (pFactorizationCalculator: TLibPrimesHandle; const nPrimeFactorsCount: Cardinal; out pPrimeFactorsNeededCount: Cardinal; pPrimeFactorsBuffer: PLibPrimesPrimeFactor): TLibPrimesResult; cdecl; + + +(************************************************************************************************************************* + Function type definitions for SieveCalculator +**************************************************************************************************************************) + + (** + * Returns all prime numbers lower or equal to the sieve's value + * + * @param[in] pSieveCalculator - SieveCalculator instance. + * @param[in] nPrimesCount - Number of elements in buffer + * @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. + * @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value + * @return error code or 0 (success) + *) + TLibPrimesSieveCalculator_GetPrimesFunc = function (pSieveCalculator: TLibPrimesHandle; const nPrimesCount: Cardinal; out pPrimesNeededCount: Cardinal; pPrimesBuffer: PQWord): TLibPrimesResult; cdecl; + +(************************************************************************************************************************* + Global function definitions +**************************************************************************************************************************) + + (** + * Creates a new FactorizationCalculator instance + * + * @param[out] pInstance - New FactorizationCalculator instance + * @return error code or 0 (success) + *) + TLibPrimesCreateFactorizationCalculatorFunc = function (out pInstance: TLibPrimesHandle): TLibPrimesResult; cdecl; + + (** + * Creates a new SieveCalculator instance + * + * @param[out] pInstance - New SieveCalculator instance + * @return error code or 0 (success) + *) + TLibPrimesCreateSieveCalculatorFunc = function (out pInstance: TLibPrimesHandle): TLibPrimesResult; cdecl; + + (** + * Releases the memory of an Instance + * + * @param[in] pInstance - Instance Handle + * @return error code or 0 (success) + *) + TLibPrimesReleaseInstanceFunc = function (const pInstance: TLibPrimesHandle): TLibPrimesResult; cdecl; + + (** + * retrieves the current version of the library. + * + * @param[out] pMajor - returns the major version of the library + * @param[out] pMinor - returns the minor version of the library + * @param[out] pMicro - returns the micro version of the library + * @return error code or 0 (success) + *) + TLibPrimesGetLibraryVersionFunc = function (out pMajor: Cardinal; out pMinor: Cardinal; out pMicro: Cardinal): TLibPrimesResult; cdecl; + + (** + * Handles Library Journaling + * + * @param[in] pFileName - Journal FileName + * @return error code or 0 (success) + *) + TLibPrimesSetJournalFunc = function (const pFileName: PAnsiChar): TLibPrimesResult; cdecl; + +(************************************************************************************************************************* + Exception definition +**************************************************************************************************************************) + + ELibPrimesException = class (Exception) + private + FErrorCode: TLibPrimesResult; + FCustomMessage: String; + public + property ErrorCode: TLibPrimesResult read FErrorCode; + property CustomMessage: String read FCustomMessage; + constructor Create (AErrorCode: TLibPrimesResult); + constructor CreateCustomMessage (AErrorCode: TLibPrimesResult; AMessage: String); + end; + +(************************************************************************************************************************* + Base class definition +**************************************************************************************************************************) + + TLibPrimesBaseClass = class (TObject) + private + FWrapper: TLibPrimesWrapper; + FHandle: TLibPrimesHandle; + public + constructor Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + destructor Destroy; override; + end; + + +(************************************************************************************************************************* + Class definition for Calculator +**************************************************************************************************************************) + + TLibPrimesCalculator = class (TLibPrimesBaseClass) + private + public + constructor Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + destructor Destroy; override; + function GetValue(): QWord; + procedure SetValue(const AValue: QWord); + procedure SetProgressCallback(const AProgressCallback: PLibPrimes_ProgressCallback); + procedure Calculate(); + end; + + +(************************************************************************************************************************* + Class definition for FactorizationCalculator +**************************************************************************************************************************) + + TLibPrimesFactorizationCalculator = class (TLibPrimesCalculator) + private + public + constructor Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + destructor Destroy; override; + procedure GetPrimeFactors(out APrimeFactors: ArrayOfLibPrimesPrimeFactor); + end; + + +(************************************************************************************************************************* + Class definition for SieveCalculator +**************************************************************************************************************************) + + TLibPrimesSieveCalculator = class (TLibPrimesCalculator) + private + public + constructor Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + destructor Destroy; override; + procedure GetPrimes(out APrimes: TQWordDynArray); + end; + +(************************************************************************************************************************* + Wrapper definition +**************************************************************************************************************************) + + TLibPrimesWrapper = class (TObject) + private + FModule: HMODULE; + FLibPrimesCalculator_GetValueFunc: TLibPrimesCalculator_GetValueFunc; + FLibPrimesCalculator_SetValueFunc: TLibPrimesCalculator_SetValueFunc; + FLibPrimesCalculator_SetProgressCallbackFunc: TLibPrimesCalculator_SetProgressCallbackFunc; + FLibPrimesCalculator_CalculateFunc: TLibPrimesCalculator_CalculateFunc; + FLibPrimesFactorizationCalculator_GetPrimeFactorsFunc: TLibPrimesFactorizationCalculator_GetPrimeFactorsFunc; + FLibPrimesSieveCalculator_GetPrimesFunc: TLibPrimesSieveCalculator_GetPrimesFunc; + FLibPrimesCreateFactorizationCalculatorFunc: TLibPrimesCreateFactorizationCalculatorFunc; + FLibPrimesCreateSieveCalculatorFunc: TLibPrimesCreateSieveCalculatorFunc; + FLibPrimesReleaseInstanceFunc: TLibPrimesReleaseInstanceFunc; + FLibPrimesGetLibraryVersionFunc: TLibPrimesGetLibraryVersionFunc; + FLibPrimesSetJournalFunc: TLibPrimesSetJournalFunc; + + {$IFDEF MSWINDOWS} + function LoadFunction (AFunctionName: AnsiString; FailIfNotExistent: Boolean = True): FARPROC; + {$ELSE} + function LoadFunction (AFunctionName: AnsiString; FailIfNotExistent: Boolean = True): Pointer; + {$ENDIF MSWINDOWS} + + protected + property LibPrimesCalculator_GetValueFunc: TLibPrimesCalculator_GetValueFunc read FLibPrimesCalculator_GetValueFunc; + property LibPrimesCalculator_SetValueFunc: TLibPrimesCalculator_SetValueFunc read FLibPrimesCalculator_SetValueFunc; + property LibPrimesCalculator_SetProgressCallbackFunc: TLibPrimesCalculator_SetProgressCallbackFunc read FLibPrimesCalculator_SetProgressCallbackFunc; + property LibPrimesCalculator_CalculateFunc: TLibPrimesCalculator_CalculateFunc read FLibPrimesCalculator_CalculateFunc; + property LibPrimesFactorizationCalculator_GetPrimeFactorsFunc: TLibPrimesFactorizationCalculator_GetPrimeFactorsFunc read FLibPrimesFactorizationCalculator_GetPrimeFactorsFunc; + property LibPrimesSieveCalculator_GetPrimesFunc: TLibPrimesSieveCalculator_GetPrimesFunc read FLibPrimesSieveCalculator_GetPrimesFunc; + property LibPrimesCreateFactorizationCalculatorFunc: TLibPrimesCreateFactorizationCalculatorFunc read FLibPrimesCreateFactorizationCalculatorFunc; + property LibPrimesCreateSieveCalculatorFunc: TLibPrimesCreateSieveCalculatorFunc read FLibPrimesCreateSieveCalculatorFunc; + property LibPrimesReleaseInstanceFunc: TLibPrimesReleaseInstanceFunc read FLibPrimesReleaseInstanceFunc; + property LibPrimesGetLibraryVersionFunc: TLibPrimesGetLibraryVersionFunc read FLibPrimesGetLibraryVersionFunc; + property LibPrimesSetJournalFunc: TLibPrimesSetJournalFunc read FLibPrimesSetJournalFunc; + procedure CheckError (AInstance: TLibPrimesBaseClass; AErrorCode: TLibPrimesResult); + public + constructor Create (ADLLName: String); + destructor Destroy; override; + function CreateFactorizationCalculator(): TLibPrimesFactorizationCalculator; + function CreateSieveCalculator(): TLibPrimesSieveCalculator; + procedure ReleaseInstance(const AInstance: TLibPrimesBaseClass); + procedure GetLibraryVersion(out AMajor: Cardinal; out AMinor: Cardinal; out AMicro: Cardinal); + procedure SetJournal(const AFileName: String); + end; + + +implementation + + +(************************************************************************************************************************* + Exception implementation +**************************************************************************************************************************) + + constructor ELibPrimesException.Create (AErrorCode: TLibPrimesResult); + var + ADescription: String; + begin + FErrorCode := AErrorCode; + case FErrorCode of + LIBPRIMES_ERROR_NOTIMPLEMENTED: ADescription := 'functionality not implemented'; + LIBPRIMES_ERROR_INVALIDPARAM: ADescription := 'an invalid parameter was passed'; + LIBPRIMES_ERROR_INVALIDCAST: ADescription := 'a type cast failed'; + LIBPRIMES_ERROR_BUFFERTOOSMALL: ADescription := 'a provided buffer is too small'; + LIBPRIMES_ERROR_GENERICEXCEPTION: ADescription := 'a generic exception occurred'; + LIBPRIMES_ERROR_COULDNOTLOADLIBRARY: ADescription := 'the library could not be loaded'; + LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT: ADescription := 'a required exported symbol could not be found in the library'; + LIBPRIMES_ERROR_NORESULTAVAILABLE: ADescription := 'no result is available'; + LIBPRIMES_ERROR_CALCULATIONABORTED: ADescription := 'a calculation has been aborted'; + else + ADescription := 'unknown'; + end; + + inherited Create (Format ('Prime Numbers Interface Error - %s (#%d)', [ ADescription, AErrorCode ])); + end; + + constructor ELibPrimesException.CreateCustomMessage (AErrorCode: TLibPrimesResult; AMessage: String); + begin + FCustomMessage := AMessage; + FErrorCode := AErrorCode; + inherited Create (Format ('%s (%d)', [FCustomMessage, AErrorCode])); + end; + +(************************************************************************************************************************* + Base class implementation +**************************************************************************************************************************) + + constructor TLibPrimesBaseClass.Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + begin + if not Assigned (AWrapper) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + if not Assigned (AHandle) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + inherited Create (); + FWrapper := AWrapper; + FHandle := AHandle; + end; + + destructor TLibPrimesBaseClass.Destroy; + begin + FWrapper.ReleaseInstance(self); + inherited; + end; + +(************************************************************************************************************************* + Class implementation for Calculator +**************************************************************************************************************************) + + constructor TLibPrimesCalculator.Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + begin + inherited Create (AWrapper, AHandle); + end; + + destructor TLibPrimesCalculator.Destroy; + begin + inherited; + end; + + function TLibPrimesCalculator.GetValue(): QWord; + begin + FWrapper.CheckError (Self, FWrapper.LibPrimesCalculator_GetValueFunc (FHandle, Result)); + end; + + procedure TLibPrimesCalculator.SetValue(const AValue: QWord); + begin + FWrapper.CheckError (Self, FWrapper.LibPrimesCalculator_SetValueFunc (FHandle, AValue)); + end; + + procedure TLibPrimesCalculator.SetProgressCallback(const AProgressCallback: PLibPrimes_ProgressCallback); + begin + if not Assigned (AProgressCallback) then + raise ELibPrimesException.CreateCustomMessage (LIBPRIMES_ERROR_INVALIDPARAM, 'AProgressCallback is a nil value.'); + FWrapper.CheckError (Self, FWrapper.LibPrimesCalculator_SetProgressCallbackFunc (FHandle, AProgressCallback)); + end; + + procedure TLibPrimesCalculator.Calculate(); + begin + FWrapper.CheckError (Self, FWrapper.LibPrimesCalculator_CalculateFunc (FHandle)); + end; + +(************************************************************************************************************************* + Class implementation for FactorizationCalculator +**************************************************************************************************************************) + + constructor TLibPrimesFactorizationCalculator.Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + begin + inherited Create (AWrapper, AHandle); + end; + + destructor TLibPrimesFactorizationCalculator.Destroy; + begin + inherited; + end; + + procedure TLibPrimesFactorizationCalculator.GetPrimeFactors(out APrimeFactors: ArrayOfLibPrimesPrimeFactor); + var + countNeededPrimeFactors: Cardinal; + countWrittenPrimeFactors: Cardinal; + begin + countNeededPrimeFactors:= 0; + countWrittenPrimeFactors:= 0; + FWrapper.CheckError (Self, FWrapper.LibPrimesFactorizationCalculator_GetPrimeFactorsFunc (FHandle, 0, countNeededPrimeFactors, nil)); + SetLength (APrimeFactors, countNeededPrimeFactors); + FWrapper.CheckError (Self, FWrapper.LibPrimesFactorizationCalculator_GetPrimeFactorsFunc (FHandle, countNeededPrimeFactors, countWrittenPrimeFactors, @APrimeFactors[0])); + end; + +(************************************************************************************************************************* + Class implementation for SieveCalculator +**************************************************************************************************************************) + + constructor TLibPrimesSieveCalculator.Create (AWrapper: TLibPrimesWrapper; AHandle: TLibPrimesHandle); + begin + inherited Create (AWrapper, AHandle); + end; + + destructor TLibPrimesSieveCalculator.Destroy; + begin + inherited; + end; + + procedure TLibPrimesSieveCalculator.GetPrimes(out APrimes: TQWordDynArray); + var + countNeededPrimes: Cardinal; + countWrittenPrimes: Cardinal; + begin + countNeededPrimes:= 0; + countWrittenPrimes:= 0; + FWrapper.CheckError (Self, FWrapper.LibPrimesSieveCalculator_GetPrimesFunc (FHandle, 0, countNeededPrimes, nil)); + SetLength (APrimes, countNeededPrimes); + FWrapper.CheckError (Self, FWrapper.LibPrimesSieveCalculator_GetPrimesFunc (FHandle, countNeededPrimes, countWrittenPrimes, @APrimes[0])); + end; + +(************************************************************************************************************************* + Wrapper class implementation +**************************************************************************************************************************) + + constructor TLibPrimesWrapper.Create (ADLLName: String); + {$IFDEF MSWINDOWS} + var + AWideString: WideString; + {$ENDIF MSWINDOWS} + begin + inherited Create; + {$IFDEF MSWINDOWS} + AWideString := UTF8Decode(ADLLName + #0); + FModule := LoadLibraryW (PWideChar (AWideString)); + {$ELSE} + FModule := dynlibs.LoadLibrary (ADLLName); + {$ENDIF MSWINDOWS} + if FModule = 0 then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_COULDNOTLOADLIBRARY); + + FLibPrimesCalculator_GetValueFunc := LoadFunction ('libprimes_calculator_getvalue'); + FLibPrimesCalculator_SetValueFunc := LoadFunction ('libprimes_calculator_setvalue'); + FLibPrimesCalculator_SetProgressCallbackFunc := LoadFunction ('libprimes_calculator_setprogresscallback'); + FLibPrimesCalculator_CalculateFunc := LoadFunction ('libprimes_calculator_calculate'); + FLibPrimesFactorizationCalculator_GetPrimeFactorsFunc := LoadFunction ('libprimes_factorizationcalculator_getprimefactors'); + FLibPrimesSieveCalculator_GetPrimesFunc := LoadFunction ('libprimes_sievecalculator_getprimes'); + FLibPrimesCreateFactorizationCalculatorFunc := LoadFunction ('libprimes_createfactorizationcalculator'); + FLibPrimesCreateSieveCalculatorFunc := LoadFunction ('libprimes_createsievecalculator'); + FLibPrimesReleaseInstanceFunc := LoadFunction ('libprimes_releaseinstance'); + FLibPrimesGetLibraryVersionFunc := LoadFunction ('libprimes_getlibraryversion'); + FLibPrimesSetJournalFunc := LoadFunction ('libprimes_setjournal'); + end; + + destructor TLibPrimesWrapper.Destroy; + begin + {$IFDEF MSWINDOWS} + if FModule <> 0 then + FreeLibrary (FModule); + {$ELSE} + if FModule <> 0 then + UnloadLibrary (FModule); + {$ENDIF MSWINDOWS} + inherited; + end; + + procedure TLibPrimesWrapper.CheckError (AInstance: TLibPrimesBaseClass; AErrorCode: TLibPrimesResult); + begin + if AInstance <> nil then begin + if AInstance.FWrapper <> Self then + raise ELibPrimesException.CreateCustomMessage (LIBPRIMES_ERROR_INVALIDCAST, 'invalid wrapper call'); + end; + if AErrorCode <> LIBPRIMES_SUCCESS then + raise ELibPrimesException.Create (AErrorCode); + end; + + {$IFDEF MSWINDOWS} + function TLibPrimesWrapper.LoadFunction (AFunctionName: AnsiString; FailIfNotExistent: Boolean): FARPROC; + begin + Result := GetProcAddress (FModule, PAnsiChar (AFunctionName)); + if FailIfNotExistent and not Assigned (Result) then + raise ELibPrimesException.CreateCustomMessage (LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT, 'could not find function ' + AFunctionName); + end; + {$ELSE} + function TLibPrimesWrapper.LoadFunction (AFunctionName: AnsiString; FailIfNotExistent: Boolean): Pointer; + begin + Result := dynlibs.GetProcAddress (FModule, AFunctionName); + if FailIfNotExistent and not Assigned (Result) then + raise ELibPrimesException.CreateCustomMessage (LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT, 'could not find function ' + AFunctionName); + end; + {$ENDIF MSWINDOWS} + + function TLibPrimesWrapper.CreateFactorizationCalculator(): TLibPrimesFactorizationCalculator; + var + HInstance: TLibPrimesHandle; + begin + Result := nil; + HInstance := nil; + CheckError (nil, LibPrimesCreateFactorizationCalculatorFunc (HInstance)); + if Assigned (HInstance) then + Result := TLibPrimesFactorizationCalculator.Create (Self, HInstance); + end; + + function TLibPrimesWrapper.CreateSieveCalculator(): TLibPrimesSieveCalculator; + var + HInstance: TLibPrimesHandle; + begin + Result := nil; + HInstance := nil; + CheckError (nil, LibPrimesCreateSieveCalculatorFunc (HInstance)); + if Assigned (HInstance) then + Result := TLibPrimesSieveCalculator.Create (Self, HInstance); + end; + + procedure TLibPrimesWrapper.ReleaseInstance(const AInstance: TLibPrimesBaseClass); + begin + if not Assigned (AInstance) then + raise ELibPrimesException.CreateCustomMessage (LIBPRIMES_ERROR_INVALIDPARAM, 'AInstance is a nil value.'); + CheckError (nil, LibPrimesReleaseInstanceFunc (AInstance.FHandle)); + end; + + procedure TLibPrimesWrapper.GetLibraryVersion(out AMajor: Cardinal; out AMinor: Cardinal; out AMicro: Cardinal); + begin + CheckError (nil, LibPrimesGetLibraryVersionFunc (AMajor, AMinor, AMicro)); + end; + + procedure TLibPrimesWrapper.SetJournal(const AFileName: String); + begin + CheckError (nil, LibPrimesSetJournalFunc (PAnsiChar (AFileName))); + end; + + +end. diff --git a/Examples/Primes/LibPrimes_component/Bindings/Python/LibPrimes.py b/Examples/Primes/LibPrimes_component/Bindings/Python/LibPrimes.py new file mode 100644 index 00000000..1298c585 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Bindings/Python/LibPrimes.py @@ -0,0 +1,231 @@ +'''++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Python file in order to allow an easy + use of Prime Numbers Interface + +Interface version: 1.2.0 + +''' + + +import ctypes +import platform +import enum + +'''Definition of domain specific exception +''' +class ELibPrimesException(Exception): + def __init__(self, code, message = ''): + self._code = code + self._message = message + + def __str__(self): + if self._message: + return 'LibPrimesException ' + str(self._code) + ': '+ str(self._message) + return 'LibPrimesException ' + str(self._code) + +'''Definition Error Codes +''' +class LibPrimesErrorCodes(enum.IntEnum): + SUCCESS = 0 + NOTIMPLEMENTED = 1 + INVALIDPARAM = 2 + INVALIDCAST = 3 + BUFFERTOOSMALL = 4 + GENERICEXCEPTION = 5 + COULDNOTLOADLIBRARY = 6 + COULDNOTFINDLIBRARYEXPORT = 7 + NORESULTAVAILABLE = 8 + CALCULATIONABORTED = 9 + +'''Definition of Structs +''' +'''Definition of LibPrimesPrimeFactor +''' +class LibPrimesPrimeFactor(ctypes.Structure): + _pack_ = 1 + _fields_ = [ + ("Prime", ctypes.c_uint64), + ("Multiplicity", ctypes.c_uint32) + ] + +'''Definition of Function Types +''' +'''Definition of LibPrimesProgressCallback + Callback to report calculation progress and query whether it should be aborted +''' +LibPrimesProgressCallback = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_float, ctypes.POINTER(ctypes.c_bool)) + + +'''Wrapper Class Implementation +''' +class LibPrimesWrapper: + + def __init__(self, libraryName): + ending = '' + if platform.system() == 'Windows': + ending = 'dll' + elif platform.system() == 'Linux': + ending = 'so' + elif platform.system() == 'Darwin': + ending = 'dylib' + else: + raise ELibPrimesException(LibPrimesErrorCodes.COULDNOTLOADLIBRARY) + + path = libraryName + '.' + ending + + try: + self.lib = ctypes.CDLL(path) + except Exception as e: + raise ELibPrimesException(LibPrimesErrorCodes.COULDNOTLOADLIBRARY, str(e) + '| "'+path + '"' ) + + self._loadFunctionTable() + + def _loadFunctionTable(self): + try: + self.lib.libprimes_createfactorizationcalculator.restype = ctypes.c_int64 + self.lib.libprimes_createfactorizationcalculator.argtypes = [ctypes.POINTER(ctypes.c_void_p)] + + self.lib.libprimes_createsievecalculator.restype = ctypes.c_int64 + self.lib.libprimes_createsievecalculator.argtypes = [ctypes.POINTER(ctypes.c_void_p)] + + self.lib.libprimes_releaseinstance.restype = ctypes.c_int64 + self.lib.libprimes_releaseinstance.argtypes = [ctypes.c_void_p] + + self.lib.libprimes_getlibraryversion.restype = ctypes.c_int64 + self.lib.libprimes_getlibraryversion.argtypes = [ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(ctypes.c_uint32)] + + self.lib.libprimes_setjournal.restype = ctypes.c_int64 + self.lib.libprimes_setjournal.argtypes = [ctypes.c_char_p] + + self.lib.libprimes_calculator_getvalue.restype = ctypes.c_int64 + self.lib.libprimes_calculator_getvalue.argtypes = [ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint64)] + + self.lib.libprimes_calculator_setvalue.restype = ctypes.c_int64 + self.lib.libprimes_calculator_setvalue.argtypes = [ctypes.c_void_p, ctypes.c_uint64] + + self.lib.libprimes_calculator_setprogresscallback.restype = ctypes.c_int64 + self.lib.libprimes_calculator_setprogresscallback.argtypes = [ctypes.c_void_p, LibPrimesProgressCallback] + + self.lib.libprimes_calculator_calculate.restype = ctypes.c_int64 + self.lib.libprimes_calculator_calculate.argtypes = [ctypes.c_void_p] + + self.lib.libprimes_factorizationcalculator_getprimefactors.restype = ctypes.c_int64 + self.lib.libprimes_factorizationcalculator_getprimefactors.argtypes = [ctypes.c_void_p, ctypes.c_uint64, ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(LibPrimesPrimeFactor)] + + self.lib.libprimes_sievecalculator_getprimes.restype = ctypes.c_int64 + self.lib.libprimes_sievecalculator_getprimes.argtypes = [ctypes.c_void_p, ctypes.c_uint64, ctypes.POINTER(ctypes.c_uint64), ctypes.POINTER(ctypes.c_uint64)] + + except AttributeError as ae: + raise ELibPrimesException(LibPrimesErrorCodes.COULDNOTFINDLIBRARYEXPORT, ae.args[0]) + + def checkError(self, instance, errorCode): + if instance: + if instance._wrapper != self: + raise ELibPrimesException(LibPrimesErrorCodes.INVALIDCAST, 'invalid wrapper call') + if errorCode != LibPrimesErrorCodes.SUCCESS.value: + raise ELibPrimesException(errorCode) + + def CreateFactorizationCalculator(self): + InstanceHandle = ctypes.c_void_p() + self.checkError(None, self.lib.libprimes_createfactorizationcalculator(InstanceHandle)) + InstanceObject = LibPrimesFactorizationCalculator(InstanceHandle, self) + return InstanceObject + + def CreateSieveCalculator(self): + InstanceHandle = ctypes.c_void_p() + self.checkError(None, self.lib.libprimes_createsievecalculator(InstanceHandle)) + InstanceObject = LibPrimesSieveCalculator(InstanceHandle, self) + return InstanceObject + + def ReleaseInstance(self, InstanceObject): + self.checkError(None, self.lib.libprimes_releaseinstance(InstanceObject._handle)) + + def GetLibraryVersion(self): + pMajor = ctypes.c_uint32() + pMinor = ctypes.c_uint32() + pMicro = ctypes.c_uint32() + self.checkError(None, self.lib.libprimes_getlibraryversion(pMajor, pMinor, pMicro)) + return pMajor.value, pMinor.value, pMicro.value + + def SetJournal(self, FileName): + pFileName = ctypes.c_char_p(str.encode(FileName)) + self.checkError(None, self.lib.libprimes_setjournal(pFileName)) + +'''Base Class Implementation +''' +class LibPrimesBaseClass(): + def __init__(self, handle, wrapper): + if not handle or not wrapper: + raise ELibPrimesException() + self._handle = handle + self._wrapper = wrapper + + def __del__(self): + self._wrapper.ReleaseInstance(self) + + +'''Calculator Class Implementation +''' +class LibPrimesCalculator(LibPrimesBaseClass): + def __init__(self, handle, wrapper): + LibPrimesBaseClass.__init__(self, handle, wrapper) + + def GetValue(self): + pValue = ctypes.c_uint64() + self._wrapper.checkError(self, self._wrapper.lib.libprimes_calculator_getvalue(self._handle, pValue)) + return pValue.value + + def SetValue(self, Value): + nValue = ctypes.c_uint64(Value) + self._wrapper.checkError(self, self._wrapper.lib.libprimes_calculator_setvalue(self._handle, nValue)) + + def SetProgressCallback(self, ProgressCallbackFunc): + self._wrapper.checkError(self, self._wrapper.lib.libprimes_calculator_setprogresscallback(self._handle, ProgressCallbackFunc)) + + def Calculate(self): + self._wrapper.checkError(self, self._wrapper.lib.libprimes_calculator_calculate(self._handle)) + + + +'''FactorizationCalculator Class Implementation +''' +class LibPrimesFactorizationCalculator(LibPrimesCalculator): + def __init__(self, handle, wrapper): + LibPrimesBaseClass.__init__(self, handle, wrapper) + + def GetPrimeFactors(self): + nPrimeFactorsCount = ctypes.c_uint64(0) + nPrimeFactorsNeededCount = ctypes.c_uint64(0) + pPrimeFactorsBuffer = (LibPrimesPrimeFactor*0)() + self._wrapper.checkError(self, self._wrapper.lib.libprimes_factorizationcalculator_getprimefactors(self._handle, nPrimeFactorsCount, nPrimeFactorsNeededCount, pPrimeFactorsBuffer)) + nPrimeFactorsCount = ctypes.c_uint64(nPrimeFactorsNeededCount.value) + pPrimeFactorsBuffer = (LibPrimesPrimeFactor * nPrimeFactorsNeededCount.value)() + self._wrapper.checkError(self, self._wrapper.lib.libprimes_factorizationcalculator_getprimefactors(self._handle, nPrimeFactorsCount, nPrimeFactorsNeededCount, pPrimeFactorsBuffer)) + return [pPrimeFactorsBuffer[i] for i in range(nPrimeFactorsNeededCount.value)] + + + +'''SieveCalculator Class Implementation +''' +class LibPrimesSieveCalculator(LibPrimesCalculator): + def __init__(self, handle, wrapper): + LibPrimesBaseClass.__init__(self, handle, wrapper) + + def GetPrimes(self): + nPrimesCount = ctypes.c_uint64(0) + nPrimesNeededCount = ctypes.c_uint64(0) + pPrimesBuffer = (ctypes.c_uint64*0)() + self._wrapper.checkError(self, self._wrapper.lib.libprimes_sievecalculator_getprimes(self._handle, nPrimesCount, nPrimesNeededCount, pPrimesBuffer)) + nPrimesCount = ctypes.c_uint64(nPrimesNeededCount.value) + pPrimesBuffer = (ctypes.c_uint64 * nPrimesNeededCount.value)() + self._wrapper.checkError(self, self._wrapper.lib.libprimes_sievecalculator_getprimes(self._handle, nPrimesCount, nPrimesNeededCount, pPrimesBuffer)) + return [pPrimesBuffer[i] for i in range(nPrimesNeededCount.value)] + + diff --git a/Examples/Primes/LibPrimes_component/Examples/Python/LibPrimes_Example.py b/Examples/Primes/LibPrimes_component/Examples/Python/LibPrimes_Example.py index 298f7fe7..c6d26a70 100644 --- a/Examples/Primes/LibPrimes_component/Examples/Python/LibPrimes_Example.py +++ b/Examples/Primes/LibPrimes_component/Examples/Python/LibPrimes_Example.py @@ -29,7 +29,18 @@ def main(): major, minor, micro = wrapper.GetLibraryVersion() print("LibPrimes version: {:d}.{:d}.{:d}".format(major, minor, micro)) - + sieve = wrapper.CreateSieveCalculator() + sieve.SetValue(105) + sieve.Calculate() + primes = sieve.GetPrimes() + print("Primes <= {:d} = [".format(sieve.GetValue()), end="") + commaString = ", " + for i in range(0, len(primes)): + if i == len(primes) - 1: + commaString = "" + print("{:d}".format(primes[i]), end=commaString) + print("]") + factorization = wrapper.CreateFactorizationCalculator() factorization.SetValue(735) cTypesCallback = LibPrimes.LibPrimesProgressCallback(progressCallback) @@ -44,6 +55,8 @@ def main(): productString = "\n" print(" {:d}^{:d} ".format(pF.Prime, pF.Multiplicity), end=productString) + + if __name__ == "__main__": try: main() diff --git a/Examples/Primes/LibPrimes_component/Implementations/Cpp/Stub/libprimes_sievecalculator.cpp b/Examples/Primes/LibPrimes_component/Implementations/Cpp/Stub/libprimes_sievecalculator.cpp index 79b8fb31..3dbd7289 100644 --- a/Examples/Primes/LibPrimes_component/Implementations/Cpp/Stub/libprimes_sievecalculator.cpp +++ b/Examples/Primes/LibPrimes_component/Implementations/Cpp/Stub/libprimes_sievecalculator.cpp @@ -12,6 +12,7 @@ Abstract: This is a stub class definition of CLibPrimesSieveCalculator #include "libprimes_interfaceexception.hpp" // Include custom headers here. +#include using namespace LibPrimes; @@ -29,9 +30,9 @@ void CLibPrimesSieveCalculator::Calculate() strikenOut[i] = i < 2; } - unsigned long sqrtValue = (unsigned long)(sqrt(m_value)); + unsigned long sqrtValue = (unsigned long)(std::sqrt(m_value)); - int progressStep = (int)ceil(sqrtValue / 20.0f); + int progressStep = (int)std::ceil(sqrtValue / 20.0f); for (unsigned long long i = 2; i <= sqrtValue; i++) { diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/.gitignore b/Examples/Primes/LibPrimes_component/Implementations/Pascal/.gitignore new file mode 100644 index 00000000..c6415d19 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/.gitignore @@ -0,0 +1,3 @@ +bin +lib + diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes.lpr b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes.lpr new file mode 100644 index 00000000..90795bdb --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes.lpr @@ -0,0 +1,44 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal project file in order to allow easy +development of Prime Numbers Interface. + +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +library libprimes; + +uses +{$IFDEF UNIX} + cthreads, +{$ENDIF UNIX} + syncobjs, + libprimes_types, + libprimes_exports, + Classes, + sysutils; + +exports + libprimes_calculator_getvalue, + libprimes_calculator_setvalue, + libprimes_calculator_setprogresscallback, + libprimes_calculator_calculate, + libprimes_factorizationcalculator_getprimefactors, + libprimes_sievecalculator_getprimes, + libprimes_createfactorizationcalculator, + libprimes_createsievecalculator, + libprimes_releaseinstance, + libprimes_getlibraryversion, + libprimes_setjournal; + +begin + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exception.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exception.pas new file mode 100644 index 00000000..d3bd6865 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exception.pas @@ -0,0 +1,70 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal exception class definition file in order to allow easy +development of Prime Numbers Interface. The functions in this file need to be implemented. It needs to be generated only once. + +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +unit libprimes_exception; + +interface + +uses + libprimes_types, + Classes, + sysutils; + +type + ELibPrimesException = class (Exception) + private + FErrorCode: TLibPrimesResult; + FCustomMessage: String; + public + property ErrorCode: TLibPrimesResult read FErrorCode; + property CustomMessage: String read FCustomMessage; + constructor Create (AErrorCode: TLibPrimesResult); + constructor CreateCustomMessage (AErrorCode: TLibPrimesResult; AMessage: String); + end; + + +implementation + + constructor ELibPrimesException.Create (AErrorCode: TLibPrimesResult); + var + ADescription: String; + begin + FErrorCode := AErrorCode; + case FErrorCode of + LIBPRIMES_ERROR_NOTIMPLEMENTED: ADescription := 'functionality not implemented'; + LIBPRIMES_ERROR_INVALIDPARAM: ADescription := 'an invalid parameter was passed'; + LIBPRIMES_ERROR_INVALIDCAST: ADescription := 'a type cast failed'; + LIBPRIMES_ERROR_BUFFERTOOSMALL: ADescription := 'a provided buffer is too small'; + LIBPRIMES_ERROR_GENERICEXCEPTION: ADescription := 'a generic exception occurred'; + LIBPRIMES_ERROR_COULDNOTLOADLIBRARY: ADescription := 'the library could not be loaded'; + LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT: ADescription := 'a required exported symbol could not be found in the library'; + LIBPRIMES_ERROR_NORESULTAVAILABLE: ADescription := 'no result is available'; + LIBPRIMES_ERROR_CALCULATIONABORTED: ADescription := 'a calculation has been aborted'; + else + ADescription := 'unknown'; + end; + + inherited Create (Format ('Prime Numbers Interface Error - %s (#%d)', [ ADescription, AErrorCode ])); + end; + + constructor ELibPrimesException.CreateCustomMessage (AErrorCode: TLibPrimesResult; AMessage: String); + begin + FCustomMessage := AMessage; + FErrorCode := AErrorCode; + inherited Create (Format ('%s (%d)', [FCustomMessage, AErrorCode])); + end; + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exports.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exports.pas new file mode 100644 index 00000000..53cc249e --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_exports.pas @@ -0,0 +1,436 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal export implementation file in order to allow easy +development of Prime Numbers Interface. The functions in this file need to be implemented. It needs to be generated only once. + +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +unit libprimes_exports; + +interface + +uses + libprimes_impl, + libprimes_types, + libprimes_interfaces, + libprimes_exception, + Classes, + sysutils; + +(************************************************************************************************************************* + Class export definition of Calculator +**************************************************************************************************************************) + +(** +* Returns the current value of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @param[out] pValue - The current value of this Calculator +* @return error code or 0 (success) +*) +function libprimes_calculator_getvalue (pCalculator: TLibPrimesHandle; pValue: PQWord): TLibPrimesResult; cdecl; + +(** +* Sets the value to be factorized +* +* @param[in] pCalculator - Calculator instance. +* @param[in] nValue - The value to be factorized +* @return error code or 0 (success) +*) +function libprimes_calculator_setvalue (pCalculator: TLibPrimesHandle; nValue: QWord): TLibPrimesResult; cdecl; + +(** +* Sets the progress callback function +* +* @param[in] pCalculator - Calculator instance. +* @param[in] pProgressCallback - The progress callback +* @return error code or 0 (success) +*) +function libprimes_calculator_setprogresscallback (pCalculator: TLibPrimesHandle; pProgressCallback: PLibPrimes_ProgressCallback): TLibPrimesResult; cdecl; + +(** +* Performs the specific calculation of this Calculator +* +* @param[in] pCalculator - Calculator instance. +* @return error code or 0 (success) +*) +function libprimes_calculator_calculate (pCalculator: TLibPrimesHandle): TLibPrimesResult; cdecl; + +(************************************************************************************************************************* + Class export definition of FactorizationCalculator +**************************************************************************************************************************) + +(** +* Returns the prime factors of this number (without multiplicity) +* +* @param[in] pFactorizationCalculator - FactorizationCalculator instance. +* @param[in] nPrimeFactorsCount - Number of elements in buffer +* @param[out] pPrimeFactorsNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimeFactorsBuffer - PrimeFactor buffer of The prime factors of this number +* @return error code or 0 (success) +*) +function libprimes_factorizationcalculator_getprimefactors (pFactorizationCalculator: TLibPrimesHandle; nPrimeFactorsCount: Cardinal; pPrimeFactorsNeededCount: PCardinal; pPrimeFactorsBuffer: PLibPrimesPrimeFactor): TLibPrimesResult; cdecl; + +(************************************************************************************************************************* + Class export definition of SieveCalculator +**************************************************************************************************************************) + +(** +* Returns all prime numbers lower or equal to the sieve's value +* +* @param[in] pSieveCalculator - SieveCalculator instance. +* @param[in] nPrimesCount - Number of elements in buffer +* @param[out] pPrimesNeededCount - will be filled with the count of the written elements, or needed buffer size. +* @param[out] pPrimesBuffer - uint64 buffer of The primes lower or equal to the sieve's value +* @return error code or 0 (success) +*) +function libprimes_sievecalculator_getprimes (pSieveCalculator: TLibPrimesHandle; nPrimesCount: Cardinal; pPrimesNeededCount: PCardinal; pPrimesBuffer: PQWord): TLibPrimesResult; cdecl; + +(************************************************************************************************************************* + Global function export definition +**************************************************************************************************************************) + +(** +* Creates a new FactorizationCalculator instance +* +* @param[out] pInstance - New FactorizationCalculator instance +* @return error code or 0 (success) +*) +function libprimes_createfactorizationcalculator (pInstance: PLibPrimesHandle): TLibPrimesResult; cdecl; + +(** +* Creates a new SieveCalculator instance +* +* @param[out] pInstance - New SieveCalculator instance +* @return error code or 0 (success) +*) +function libprimes_createsievecalculator (pInstance: PLibPrimesHandle): TLibPrimesResult; cdecl; + +(** +* Releases the memory of an Instance +* +* @param[in] pInstance - Instance Handle +* @return error code or 0 (success) +*) +function libprimes_releaseinstance (pInstance: TLibPrimesHandle): TLibPrimesResult; cdecl; + +(** +* retrieves the current version of the library. +* +* @param[out] pMajor - returns the major version of the library +* @param[out] pMinor - returns the minor version of the library +* @param[out] pMicro - returns the micro version of the library +* @return error code or 0 (success) +*) +function libprimes_getlibraryversion (pMajor: PCardinal; pMinor: PCardinal; pMicro: PCardinal): TLibPrimesResult; cdecl; + +(** +* Handles Library Journaling +* +* @param[in] pFileName - Journal FileName +* @return error code or 0 (success) +*) +function libprimes_setjournal (pFileName: PAnsiChar): TLibPrimesResult; cdecl; + +implementation + +function libprimes_calculator_getvalue (pCalculator: TLibPrimesHandle; pValue: PQWord): TLibPrimesResult; cdecl; +var + ResultValue: QWord; + ObjectCalculator: TObject; + IntfCalculator: ILibPrimesCalculator; +begin + try + if not Assigned (pValue) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + if not Assigned (pCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectCalculator := TObject (pCalculator); + if Supports (ObjectCalculator, ILibPrimesCalculator) then begin + IntfCalculator := ObjectCalculator as ILibPrimesCalculator; + ResultValue := IntfCalculator.GetValue(); + + pValue^ := ResultValue; + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_calculator_setvalue (pCalculator: TLibPrimesHandle; nValue: QWord): TLibPrimesResult; cdecl; +var + ObjectCalculator: TObject; + IntfCalculator: ILibPrimesCalculator; +begin + try + if not Assigned (pCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectCalculator := TObject (pCalculator); + if Supports (ObjectCalculator, ILibPrimesCalculator) then begin + IntfCalculator := ObjectCalculator as ILibPrimesCalculator; + IntfCalculator.SetValue(nValue); + + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_calculator_setprogresscallback (pCalculator: TLibPrimesHandle; pProgressCallback: PLibPrimes_ProgressCallback): TLibPrimesResult; cdecl; +var + ObjectCalculator: TObject; + IntfCalculator: ILibPrimesCalculator; +begin + try + if not Assigned (pCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectCalculator := TObject (pCalculator); + if Supports (ObjectCalculator, ILibPrimesCalculator) then begin + IntfCalculator := ObjectCalculator as ILibPrimesCalculator; + IntfCalculator.SetProgressCallback(pProgressCallback); + + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_calculator_calculate (pCalculator: TLibPrimesHandle): TLibPrimesResult; cdecl; +var + ObjectCalculator: TObject; + IntfCalculator: ILibPrimesCalculator; +begin + try + if not Assigned (pCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectCalculator := TObject (pCalculator); + if Supports (ObjectCalculator, ILibPrimesCalculator) then begin + IntfCalculator := ObjectCalculator as ILibPrimesCalculator; + IntfCalculator.Calculate(); + + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_factorizationcalculator_getprimefactors (pFactorizationCalculator: TLibPrimesHandle; nPrimeFactorsCount: Cardinal; pPrimeFactorsNeededCount: PCardinal; pPrimeFactorsBuffer: PLibPrimesPrimeFactor): TLibPrimesResult; cdecl; +var + ObjectFactorizationCalculator: TObject; + IntfFactorizationCalculator: ILibPrimesFactorizationCalculator; +begin + try + if ((not Assigned (pPrimeFactorsNeededCount)) and (not Assigned(pPrimeFactorsBuffer))) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + if not Assigned (pFactorizationCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectFactorizationCalculator := TObject (pFactorizationCalculator); + if Supports (ObjectFactorizationCalculator, ILibPrimesFactorizationCalculator) then begin + IntfFactorizationCalculator := ObjectFactorizationCalculator as ILibPrimesFactorizationCalculator; + IntfFactorizationCalculator.GetPrimeFactors(nPrimeFactorsCount, pPrimeFactorsNeededCount, pPrimeFactorsBuffer); + + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_sievecalculator_getprimes (pSieveCalculator: TLibPrimesHandle; nPrimesCount: Cardinal; pPrimesNeededCount: PCardinal; pPrimesBuffer: PQWord): TLibPrimesResult; cdecl; +var + ObjectSieveCalculator: TObject; + IntfSieveCalculator: ILibPrimesSieveCalculator; +begin + try + if ((not Assigned (pPrimesNeededCount)) and (not Assigned(pPrimesBuffer))) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + if not Assigned (pSieveCalculator) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ObjectSieveCalculator := TObject (pSieveCalculator); + if Supports (ObjectSieveCalculator, ILibPrimesSieveCalculator) then begin + IntfSieveCalculator := ObjectSieveCalculator as ILibPrimesSieveCalculator; + IntfSieveCalculator.GetPrimes(nPrimesCount, pPrimesNeededCount, pPrimesBuffer); + + end else + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_createfactorizationcalculator (pInstance: PLibPrimesHandle): TLibPrimesResult; cdecl; +var + ResultInstance: TObject; +begin + try + if not Assigned(pInstance) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ResultInstance := TLibPrimesWrapper.CreateFactorizationCalculator(); + + pInstance^ := ResultInstance; + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_createsievecalculator (pInstance: PLibPrimesHandle): TLibPrimesResult; cdecl; +var + ResultInstance: TObject; +begin + try + if not Assigned(pInstance) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + ResultInstance := TLibPrimesWrapper.CreateSieveCalculator(); + + pInstance^ := ResultInstance; + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_releaseinstance (pInstance: TLibPrimesHandle): TLibPrimesResult; cdecl; +var + ObjectInstance: TObject; +begin + try + ObjectInstance := TObject (pInstance); + if (not Supports (ObjectInstance, ILibPrimesBaseClass)) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDCAST); + + + TLibPrimesWrapper.ReleaseInstance(ObjectInstance); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_getlibraryversion (pMajor: PCardinal; pMinor: PCardinal; pMicro: PCardinal): TLibPrimesResult; cdecl; +begin + try + if (not Assigned (pMajor)) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + if (not Assigned (pMinor)) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + if (not Assigned (pMicro)) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + + TLibPrimesWrapper.GetLibraryVersion(pMajor^, pMinor^, pMicro^); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + +function libprimes_setjournal (pFileName: PAnsiChar): TLibPrimesResult; cdecl; +begin + try + if (not Assigned (pFileName)) then + raise ELibPrimesException.Create (LIBPRIMES_ERROR_INVALIDPARAM); + + TLibPrimesWrapper.SetJournal(StrPas (pFileName)); + + Result := LIBPRIMES_SUCCESS; + except + On E: ELibPrimesException do begin + Result := E.ErrorCode; + end; + On E: Exception do begin + Result := LIBPRIMES_ERROR_GENERICEXCEPTION; + end; + end; +end; + + +end. + diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_interfaces.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_interfaces.pas new file mode 100644 index 00000000..3ff944f5 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_interfaces.pas @@ -0,0 +1,75 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal interface definition file in order to allow easy +development of Prime Numbers Interface. The functions in this file need to be implemented. It needs to be generated only once. + +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +{$INTERFACES CORBA} +unit libprimes_interfaces; + +interface + +uses + libprimes_types, + Classes, + sysutils; + + +(************************************************************************************************************************* + Interface definition for BaseClass +**************************************************************************************************************************) + +type + ILibPrimesBaseClass = interface + ['{52FDFC07-2182-454F-963F-5F0F9A621D72}'] + end; + + +(************************************************************************************************************************* + Interface definition for Calculator +**************************************************************************************************************************) + + ILibPrimesCalculator = interface (ILibPrimesBaseClass) + ['{9566C74D-1003-4C4D-BBBB-0407D1E2C649}'] + + function GetValue(): QWord; + procedure SetValue(const AValue: QWord); + procedure SetProgressCallback(const AProgressCallback: PLibPrimes_ProgressCallback); + procedure Calculate(); + end; + + +(************************************************************************************************************************* + Interface definition for FactorizationCalculator +**************************************************************************************************************************) + + ILibPrimesFactorizationCalculator = interface (ILibPrimesCalculator) + ['{81855AD8-681D-4D86-91E9-1E00167939CB}'] + + procedure GetPrimeFactors(const APrimeFactorsCount: Cardinal; PPrimeFactorsNeededCount: PCardinal; APrimeFactors: PLibPrimesPrimeFactor); + end; + + +(************************************************************************************************************************* + Interface definition for SieveCalculator +**************************************************************************************************************************) + + ILibPrimesSieveCalculator = interface (ILibPrimesCalculator) + ['{6694D2C4-22AC-4208-A007-2939487F6999}'] + + procedure GetPrimes(const APrimesCount: Cardinal; PPrimesNeededCount: PCardinal; APrimes: PQWord); + end; + +implementation + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_types.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_types.pas new file mode 100644 index 00000000..9519f3ae --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Interfaces/libprimes_types.pas @@ -0,0 +1,89 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +This file has been generated by the Automatic Component Toolkit (ACT) version 1.2.4. + +Abstract: This is an autogenerated Pascal type definition file in order to allow easy +development of Prime Numbers Interface. The functions in this file need to be implemented. It needs to be generated only once. + +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +unit libprimes_types; + +interface + +uses + Classes, + sysutils; + +(************************************************************************************************************************* + Version definition for LibPrimes +**************************************************************************************************************************) + +const + LIBPRIMES_VERSION_MAJOR = 1; + LIBPRIMES_VERSION_MINOR = 2; + LIBPRIMES_VERSION_MICRO = 0; + + +(************************************************************************************************************************* + General type definitions +**************************************************************************************************************************) + +type + TLibPrimesResult = Cardinal; + TLibPrimesHandle = Pointer; + + PLibPrimesResult = ^TLibPrimesResult; + PLibPrimesHandle = ^TLibPrimesHandle; + +(************************************************************************************************************************* + Error Constants for LibPrimes +**************************************************************************************************************************) + +const + LIBPRIMES_SUCCESS = 0; + LIBPRIMES_ERROR_NOTIMPLEMENTED = 1; + LIBPRIMES_ERROR_INVALIDPARAM = 2; + LIBPRIMES_ERROR_INVALIDCAST = 3; + LIBPRIMES_ERROR_BUFFERTOOSMALL = 4; + LIBPRIMES_ERROR_GENERICEXCEPTION = 5; + LIBPRIMES_ERROR_COULDNOTLOADLIBRARY = 6; + LIBPRIMES_ERROR_COULDNOTFINDLIBRARYEXPORT = 7; + LIBPRIMES_ERROR_NORESULTAVAILABLE = 8; + LIBPRIMES_ERROR_CALCULATIONABORTED = 9; + +(************************************************************************************************************************* + Declaration of structs +**************************************************************************************************************************) + +type + + PLibPrimesPrimeFactor = ^TLibPrimesPrimeFactor; + TLibPrimesPrimeFactor = packed record + FPrime: QWord; + FMultiplicity: Cardinal; + end; + + +(************************************************************************************************************************* + Declaration of function types +**************************************************************************************************************************) + + PLibPrimes_ProgressCallback = function(const fProgressPercentage: Single; out pShouldAbort: Cardinal): Integer; + +(************************************************************************************************************************* + Declaration of struct arrays +**************************************************************************************************************************) + + ArrayOfLibPrimesPrimeFactor = array of TLibPrimesPrimeFactor; + +implementation + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl.pas new file mode 100644 index 00000000..e1786742 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl.pas @@ -0,0 +1,67 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +Abstract: This is an autogenerated Pascal implementation file in order to allow easy +development of Prime Numbers Interface. It needs to be generated only once. +Interface version: 1.2.0 + +*) + +{$MODE DELPHI} +Unit libprimes_impl; + +interface + +uses + libprimes_types, + libprimes_exception, + libprimes_impl_factorizationcalculator, + libprimes_impl_sievecalculator, + Classes, + sysutils; + +type + TLibPrimesWrapper = class (TObject) + public + class function CreateFactorizationCalculator(): TObject; + class function CreateSieveCalculator(): TObject; + class procedure ReleaseInstance(AInstance: TObject); + class procedure GetLibraryVersion(out AMajor: Cardinal; out AMinor: Cardinal; out AMicro: Cardinal); + class procedure SetJournal(const AFileName: String); + end; + + +implementation + +class function TLibPrimesWrapper.CreateFactorizationCalculator(): TObject; +begin + result := TLibPrimesFactorizationCalculator.Create(); +end; + +class function TLibPrimesWrapper.CreateSieveCalculator(): TObject; +begin + result := TLibPrimesSieveCalculator.Create(); +end; + +class procedure TLibPrimesWrapper.ReleaseInstance(AInstance: TObject); +begin + FreeAndNil(AInstance); +end; + +class procedure TLibPrimesWrapper.GetLibraryVersion(out AMajor: Cardinal; out AMinor: Cardinal; out AMicro: Cardinal); +begin + AMajor := LIBPRIMES_VERSION_MAJOR; + AMinor := LIBPRIMES_VERSION_MINOR; + AMicro := LIBPRIMES_VERSION_MICRO; +end; + +class procedure TLibPrimesWrapper.SetJournal(const AFileName: String); +begin + raise ELibPrimesException (LIBPRIMES_ERROR_NOTIMPLEMENTED); +end; + + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_baseclass.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_baseclass.pas new file mode 100644 index 00000000..b7743a6e --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_baseclass.pas @@ -0,0 +1,27 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +Abstract: This is the class declaration of TLibPrimesBaseClass + +*) + +{$MODE DELPHI} +unit libprimes_impl_baseclass; + +interface + +uses + libprimes_interfaces, + Classes, + sysutils; + +type + TLibPrimesBaseClass = class (TObject, ILibPrimesBaseClass) + end; + +implementation + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_calculator.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_calculator.pas new file mode 100644 index 00000000..2852c346 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_calculator.pas @@ -0,0 +1,60 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +Abstract: This is the class declaration of TLibPrimesCalculator + +*) + +{$MODE DELPHI} +unit libprimes_impl_calculator; + +interface + +uses + libprimes_types, + libprimes_interfaces, + libprimes_exception, + libprimes_impl_baseclass, + Classes, + sysutils; + +type + TLibPrimesCalculator = class (TLibPrimesBaseClass, ILibPrimesCalculator) + private + + protected + FValue : QWord; + FProgressCallback: PLibPrimes_ProgressCallback; + public + function GetValue(): QWord; + procedure SetValue(const AValue: QWord); + procedure SetProgressCallback(const AProgressCallback: PLibPrimes_ProgressCallback); + procedure Calculate(); virtual; + end; + +implementation + +function TLibPrimesCalculator.GetValue(): QWord; +begin + result := FValue; +end; + +procedure TLibPrimesCalculator.SetValue(const AValue: QWord); +begin + FValue := AValue; +end; + +procedure TLibPrimesCalculator.SetProgressCallback(const AProgressCallback: PLibPrimes_ProgressCallback); +begin + FProgressCallback:=AProgressCallback; +end; + +procedure TLibPrimesCalculator.Calculate(); +begin + raise ELibPrimesException (LIBPRIMES_ERROR_NOTIMPLEMENTED); +end; + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_factorizationcalculator.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_factorizationcalculator.pas new file mode 100644 index 00000000..9c3ae788 --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_factorizationcalculator.pas @@ -0,0 +1,102 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +Abstract: This is the class declaration of TLibPrimesFactorizationCalculator + +*) + +{$MODE DELPHI} +unit libprimes_impl_factorizationcalculator; + +interface + +uses + libprimes_types, + libprimes_interfaces, + libprimes_exception, + libprimes_impl_calculator, + Classes, + sysutils; + +type + TLibPrimesFactorizationCalculator = class (TLibPrimesCalculator, ILibPrimesFactorizationCalculator) + private + FPrimeFactors : Array Of TLibPrimesPrimeFactor; + protected + + public + procedure GetPrimeFactors(const APrimeFactorsCount: Cardinal; PPrimeFactorsNeededCount: PCardinal; APrimeFactors: PLibPrimesPrimeFactor); + procedure Calculate(); override; + destructor Destroy(); override; + end; + +implementation + +destructor TLibPrimesFactorizationCalculator.Destroy(); +begin + SetLength(FPrimeFactors, 0); +end; + +procedure TLibPrimesFactorizationCalculator.GetPrimeFactors(const APrimeFactorsCount: Cardinal; PPrimeFactorsNeededCount: PCardinal; APrimeFactors: PLibPrimesPrimeFactor); +var + i : QWord; +begin + if (Length(FPrimeFactors) = 0) then + raise ELibPrimesException.Create(LIBPRIMES_ERROR_NORESULTAVAILABLE); + + if (assigned(PPrimeFactorsNeededCount)) then + PPrimeFactorsNeededCount^ := Length(FPrimeFactors); + + if (APrimeFactorsCount >= Length(FPrimeFactors)) then + begin + for i:=0 to Length(FPrimeFactors) -1 do begin + APrimeFactors^ := FPrimeFactors[i]; + inc(APrimeFactors); + end; + end; +end; + +procedure TLibPrimesFactorizationCalculator.Calculate(); +var + AValue: QWord; + I: QWord; + APFCount: QWord; + APrimeFactor: TLibPrimesPrimeFactor; + AShouldAbort: Cardinal; +begin + SetLength(FPrimeFactors, 0); + + APFCount := 0; + AValue := FValue; + I := 2; + while I < AValue + do begin + + + if (assigned(FProgressCallback)) then begin + AShouldAbort := 0; + FProgressCallback(1 - 1.0*AValue / FValue, AShouldAbort); + if (AShouldAbort <> 0) then + raise ELibPrimesException.Create(LIBPRIMES_ERROR_CALCULATIONABORTED); + end; + + + APrimeFactor.FMultiplicity:=0; + APrimeFactor.FPrime:=I; + while (AValue mod i = 0) do begin + inc(APrimeFactor.FMultiplicity); + AValue := AValue div I; + end; + if (APrimeFactor.FMultiplicity > 0) then begin + inc(APFCount); + SetLength(FPrimeFactors, APFCount); + FPrimeFactors[APFCount-1] := APrimeFactor; + end; + inc(I); + end; +end; + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_sievecalculator.pas b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_sievecalculator.pas new file mode 100644 index 00000000..37d0f52f --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/Stub/libprimes_impl_sievecalculator.pas @@ -0,0 +1,98 @@ +(*++ + +Copyright (C) 2018 Automatic Component Toolkit Developers + +All rights reserved. + +Abstract: This is the class declaration of TLibPrimesSieveCalculator + +*) + +{$MODE DELPHI} +unit libprimes_impl_sievecalculator; + +interface + +uses + libprimes_types, + libprimes_interfaces, + libprimes_exception, + libprimes_impl_calculator, + Classes, + sysutils; + +type + TLibPrimesSieveCalculator = class (TLibPrimesCalculator, ILibPrimesSieveCalculator) + private + FPrimes: array of QWord; + protected + + public + procedure GetPrimes(const APrimesCount: Cardinal; PPrimesNeededCount: PCardinal; APrimes: PQWord); + procedure Calculate(); override; + end; + +implementation + +procedure TLibPrimesSieveCalculator.Calculate(); +var + AStrikenOut : array of Boolean; + I, J : QWord; + ASqrtValue : QWord; + ANumPrimes: QWord; +begin + SetLength(FPrimes, 0); + ANumPrimes := 0; + + SetLength(AStrikenOut, FValue + 1); + for I := 0 to FValue do begin + AStrikenOut[I] := I < 2; + end; + + ASqrtValue := round(sqrt(FValue)); + + for I := 2 to ASqrtValue do begin + if not AStrikenOut[I] then begin + inc(ANumPrimes); + SetLength(FPrimes, ANumPrimes); + FPrimes[ANumPrimes - 1] := I; + J := I*I; + while (J <= FValue) do begin + AStrikenOut[j] := true; + inc(J, I); + end; + + end; + + end; + + for I:= ASqrtValue to FValue do begin + if not AStrikenOut[i] then begin + inc(ANumPrimes); + SetLength(FPrimes, ANumPrimes); + FPrimes[ANumPrimes - 1] := I; + end; + end; + +end; + +procedure TLibPrimesSieveCalculator.GetPrimes(const APrimesCount: Cardinal; PPrimesNeededCount: PCardinal; APrimes: PQWord); +var + i : QWord; +begin + if (Length(FPrimes) = 0) then + raise ELibPrimesException.Create(LIBPRIMES_ERROR_NORESULTAVAILABLE); + + if (assigned(PPrimesNeededCount)) then + PPrimesNeededCount^ := Length(FPrimes); + + if (APrimesCount >= Length(FPrimes)) then + begin + for i:=0 to Length(FPrimes) -1 do begin + APrimes^ := FPrimes[i]; + inc(APrimes); + end; + end; +end; + +end. diff --git a/Examples/Primes/LibPrimes_component/Implementations/Pascal/libprimes.lpi b/Examples/Primes/LibPrimes_component/Implementations/Pascal/libprimes.lpi new file mode 100644 index 00000000..2c42c0db --- /dev/null +++ b/Examples/Primes/LibPrimes_component/Implementations/Pascal/libprimes.lpi @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + <UseAppBundle Value="False" /> + <ResourceType Value="res" /> + </General> + <BuildModes Count="2"> + <Item1 Name="Release" Default="True"/> + <Item2 Name="Debug"> + <CompilerOptions> + <Version Value="11" /> + <PathDelim Value="\"/> + <Target> + <Filename Value="bin\$(TargetCPU)-$(TargetOS)\Release\projectlibprimes"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value="Stub;Interfaces"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <RelocatableUnit Value="True" /> + </CodeGeneration> + <Linking> + <Debugging> + <UseExternalDbgSyms Value="True"/> + </Debugging> + <Options> + <ExecutableType Value="Library"/> + </Options> + </Linking> + </CompilerOptions> + </Item2> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + </PublishOptions> + <RunParams> + <local> + <FormatVersion Value="1"/> + </local> + </RunParams> + <Units Count="2"> + <Unit0> + <Filename Value="Interfaces\libprimes.lpr"/> + <IsPartOfProject Value="True"/> + </Unit0> + <Unit1> + <Filename Value="Stub\libprimes.pas"/> + <IsPartOfProject Value="True"/> + </Unit1> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="bin\$(TargetCPU)-$(TargetOS)\Release\libprimes"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value="Stub;Interfaces"/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Parsing> + <SyntaxOptions> + <IncludeAssertionCode Value="True"/> + </SyntaxOptions> + </Parsing> + <CodeGeneration> + <RelocatableUnit Value="True"/> + </CodeGeneration> + <Linking> + <Debugging> + <StripSymbols Value="True"/> + <UseExternalDbgSyms Value="True"/> + </Debugging> + <Options> + <ExecutableType Value="Library"/> + </Options> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions Count="3"> + <Item1> + <Name Value="EAbort"/> + </Item1> + <Item2> + <Name Value="ECodetoolError"/> + </Item2> + <Item3> + <Name Value="EFOpenError"/> + </Item3> + </Exceptions> + </Debugging> +</CONFIG> + diff --git a/Examples/Primes/Tutorial.md b/Examples/Primes/Tutorial.md index e57df8a4..4c4ab4c9 100644 --- a/Examples/Primes/Tutorial.md +++ b/Examples/Primes/Tutorial.md @@ -691,7 +691,7 @@ time consuming calculation method of the calculators. # 5.1 IDL Open the IDL-file `libPrimes.xml` and add a new `functiontype` element within the `\<component>`-element. ```xml -<functiontype name="ProgressCallback"> +<functiontype name="ProgressCallback" description="Callback to report calculation progress and query whether it should be aborted"> <param name="ProgressPercentage" type="single" pass="in" description="How far has the calculation progressed?"/> <param name="ShouldAbort" type="bool" pass="out" description="Should the calculation be aborted?"/> </functiontype> diff --git a/Examples/Primes/libPrimes.xml b/Examples/Primes/libPrimes.xml index aec4062e..2dd0eabf 100644 --- a/Examples/Primes/libPrimes.xml +++ b/Examples/Primes/libPrimes.xml @@ -16,7 +16,7 @@ </bindings> <implementations> <implementation language="Cpp" indentation="tabs" classidentifier="" stubidentifier=""/> - <implementation language="Pascal" indentation="tabs" classidentifier="" stubidentifier=""/> + <implementation language="Pascal" indentation="tabs" classidentifier="" stubidentifier="impl"/> </implementations> <errors> @@ -36,7 +36,7 @@ <member name="Multiplicity" type="uint32" /> </struct> - <functiontype name="ProgressCallback"> + <functiontype name="ProgressCallback" description="Callback to report calculation progress and query whether it should be aborted"> <param name="ProgressPercentage" type="single" pass="in" description="How far has the calculation progressed?"/> <param name="ShouldAbort" type="bool" pass="out" description="Should the calculation be aborted?"/> </functiontype> diff --git a/Examples/UnitTest/libUnitTest.xml b/Examples/UnitTest/libUnitTest.xml index 5873a2c4..f2c56454 100644 --- a/Examples/UnitTest/libUnitTest.xml +++ b/Examples/UnitTest/libUnitTest.xml @@ -17,8 +17,8 @@ </bindings> <implementations> <implementation language="Cpp" indentation="tabs" /> - <!--<implementation language="Pascal" indentation="4spaces" /> - <implementation language="Fortran" indentation="4spaces" /> --> + <implementation language="Pascal" indentation="2spaces" stubidentifier="implementation" /> + <!--<implementation language="Fortran" indentation="4spaces" /> --> </implementations> <errors> @@ -100,12 +100,12 @@ <param name="ReturnValue" type="string" pass="return" description="returns param" /> </method> - <method name="UnitTest5" description="Passes in a basicarray"> +<!-- <method name="UnitTest5" description="Passes in a basicarray"> <param name="Value1" type="basicarray" class="uint8" pass="in" description="param1" /> <param name="Value2" type="basicarray" class="uint16" pass="in" description="param2" /> <param name="Value3" type="basicarray" class="uint32" pass="in" description="param3" /> <param name="Value4" type="basicarray" class="uint64" pass="in" description="param4" /> - </method> + </method> --> </class> diff --git a/README.md b/README.md index d735bed5..730b2e70 100644 --- a/README.md +++ b/README.md @@ -43,9 +43,9 @@ ACT supports generation of bindings and implementation stubs for C++, C, Pascal, | Binding | Status | Operating Systems | class | scalar type | struct | enumeration | string | basicarray | structarray | Callbacks | |:-----------:|:----------------------------------------------------------:|:-----------------:|:---------:|:-------------:|:-------------:|:-------------:|:-------------:|:----------:|:-----------:|:---------:| | C++ | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | -| C++ Dynamic | ![](Documentation/images/Tick.png) mature | Win | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | +| C++ Dynamic | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | | C | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | -| C Dynamic | ![](Documentation/images/Tick.png) mature | Win | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | +| C Dynamic | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | | Pascal | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | | Python | ![](Documentation/images/Tick.png) complete (but unstable) | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | | Golang | ![](Documentation/images/O.png) partial support | Win, Linux, MacOS | in,return | in,out,return | ? | ? | ? | ? | ? | - | @@ -55,7 +55,7 @@ ACT supports generation of bindings and implementation stubs for C++, C, Pascal, | Implementation | Status | Operating Systems | class | scalar type | struct | enumeration | string | basicarray | structarray | Callbacks | Journaling | |:--------------:|:-----------------------------------------------------:|:-----------------:|:---------:|:-------------:|:-------------:|:-------------:|:-------------:|:----------:|:-----------:|:---------:|:----------:| | C++ | ![](Documentation/images/Tick.png) mature | Win, Linux, MacOS | in,return | in,out,return | in,out,return | in,out,return | in,out,return | in,out | in,out | in | + | -| Pascal | ![](Documentation/images/X.png) in development | Win, Linux, MacOS | | | | | | | | | | +| Pascal | ![](Documentation/images/O.png) incomplete, untested | Win, Linux, MacOS | in,return | in,out,return | in,out,return | ??? | in,out,return | in,out | in,out | in | | ## Example diff --git a/Source/automaticcomponenttoolkit.go b/Source/automaticcomponenttoolkit.go index 7417bde4..a54bb306 100644 --- a/Source/automaticcomponenttoolkit.go +++ b/Source/automaticcomponenttoolkit.go @@ -43,8 +43,8 @@ import ( func main () { - - log.Printf ("Automatic Component Toolkit v1.2.0\n"); + ACTVersion := "1.2.4" + log.Printf ("Automatic Component Toolkit v%s\n", ACTVersion); log.Printf ("---------------------------------------\n"); if (len (os.Args) < 2) { log.Fatal ("Please run with the configuration XML as command line parameter."); @@ -74,7 +74,8 @@ func main () { } log.Printf ("Parsing Component Description File "); - var component ComponentDefinition; + var component ComponentDefinition + component.ACTVersion = ACTVersion err = xml.Unmarshal(bytes, &component) if (err != nil) { log.Fatal (err); @@ -137,9 +138,9 @@ func main () { err = CreateCTypesHeader (component, CTypesHeaderName); if (err != nil) { log.Fatal (err); - } + } - err = BuildBindingCDynamic(component, outputFolderBindingCDynamic); + err = BuildBindingCDynamic(component, outputFolderBindingCDynamic, indentString); if (err != nil) { log.Fatal (err); } @@ -163,7 +164,7 @@ func main () { log.Fatal (err); } - err = BuildBindingCppDynamic(component, outputFolderBindingCppDynamic, outputFolderExampleCppDynamic); + err = BuildBindingCppDynamic(component, outputFolderBindingCppDynamic, outputFolderExampleCppDynamic, indentString); if (err != nil) { log.Fatal (err); } @@ -223,7 +224,7 @@ func main () { log.Fatal (err); } - err = BuildBindingCDynamic(component, outputFolderBindingNode); + err = BuildBindingCDynamic(component, outputFolderBindingNode, indentString); if (err != nil) { log.Fatal (err); } diff --git a/Source/buildbindingcdynamic.go b/Source/buildbindingcdynamic.go index f54e3b4a..c2b1f5d7 100644 --- a/Source/buildbindingcdynamic.go +++ b/Source/buildbindingcdynamic.go @@ -36,9 +36,7 @@ package main import ( "fmt" - "io" "log" - "os" "path" "strings" "path/filepath" @@ -46,7 +44,7 @@ import ( // BuildBindingCDynamic builds dyanmic C-bindings of a library's API in form of dynamically loaded functions // handles. -func BuildBindingCDynamic(component ComponentDefinition, outputFolder string, ) error { +func BuildBindingCDynamic(component ComponentDefinition, outputFolder string, indentString string) error { namespace := component.NameSpace; libraryname := component.LibraryName; @@ -54,11 +52,11 @@ func BuildBindingCDynamic(component ComponentDefinition, outputFolder string, ) DynamicCHeader := path.Join(outputFolder, baseName+"_dynamic.h"); log.Printf("Creating \"%s\"", DynamicCHeader) - dynhfile, err := os.Create(DynamicCHeader) + dynhfile, err := CreateLanguageFile(DynamicCHeader, indentString) if err != nil { return err; } - WriteLicenseHeader(dynhfile, component, + dynhfile.WriteCLicenseHeader(component, fmt.Sprintf("This is an autogenerated plain C Header file in order to allow an easy\n use of %s", libraryname), true) err = buildDynamicCHeader(component, dynhfile, namespace, baseName, false) @@ -68,11 +66,11 @@ func BuildBindingCDynamic(component ComponentDefinition, outputFolder string, ) DynamicCImpl := path.Join(outputFolder, baseName+"_dynamic.cpp"); log.Printf("Creating \"%s\"", DynamicCImpl) - dyncppfile, err := os.Create(DynamicCImpl) + dyncppfile, err := CreateLanguageFile(DynamicCImpl, indentString) if err != nil { return err; } - WriteLicenseHeader(dyncppfile, component, + dyncppfile.WriteCLicenseHeader(component, fmt.Sprintf("This is an autogenerated plain C Header file in order to allow an easy\n use of %s", libraryname), true) @@ -84,21 +82,21 @@ func BuildBindingCDynamic(component ComponentDefinition, outputFolder string, ) return nil; } -func buildDynamicCHeader(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string, headerOnly bool) error { - fmt.Fprintf(w, "#ifndef __%s_DYNAMICHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "#define __%s_DYNAMICHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") +func buildDynamicCHeader(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string, headerOnly bool) error { + w.Writeln("#ifndef __%s_DYNAMICHEADER", strings.ToUpper(NameSpace)) + w.Writeln("#define __%s_DYNAMICHEADER", strings.ToUpper(NameSpace)) + w.Writeln("") - fmt.Fprintf(w, "#include \"%s_types.h\"\n", BaseName) - fmt.Fprintf(w, "\n") + w.Writeln("#include \"%s_types.h\"", BaseName) + w.Writeln("") for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Class definition for %s\n", class.ClassName) - fmt.Fprintf(w, "**************************************************************************************************************************/\n") + w.Writeln("") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Class definition for %s", class.ClassName) + w.Writeln("**************************************************************************************************************************/") for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] @@ -107,10 +105,10 @@ func buildDynamicCHeader(component ComponentDefinition, w io.Writer, NameSpace s } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Global functions\n") - fmt.Fprintf(w, "**************************************************************************************************************************/\n") + w.Writeln("") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Global functions") + w.Writeln("**************************************************************************************************************************/") global := component.Global; for j := 0; j < len(global.Methods); j++ { @@ -122,178 +120,211 @@ func buildDynamicCHeader(component ComponentDefinition, w io.Writer, NameSpace s } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Function Table Structure\n") - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "typedef struct {\n") - fmt.Fprintf(w, " void * m_LibraryHandle;\n") + w.Writeln("") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Function Table Structure") + w.Writeln("**************************************************************************************************************************/") + w.Writeln("") + w.Writeln("typedef struct {") + w.Writeln(" void * m_LibraryHandle;") for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - fmt.Fprintf(w, " P%s%s_%sPtr m_%s_%s;\n", NameSpace, class.ClassName, method.MethodName, class.ClassName, method.MethodName) + w.Writeln(" P%s%s_%sPtr m_%s_%s;", NameSpace, class.ClassName, method.MethodName, class.ClassName, method.MethodName) } } for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - fmt.Fprintf(w, " P%s%sPtr m_%s;\n", NameSpace, method.MethodName, method.MethodName) + w.Writeln(" P%s%sPtr m_%s;", NameSpace, method.MethodName, method.MethodName) } - fmt.Fprintf(w, "} s%sDynamicWrapperTable;\n", NameSpace) - fmt.Fprintf(w, "\n") + w.Writeln("} s%sDynamicWrapperTable;", NameSpace) + w.Writeln("") if (!headerOnly) { - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Load DLL dynamically\n") - fmt.Fprintf(w, "**************************************************************************************************************************/\n") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Load DLL dynamically") + w.Writeln("**************************************************************************************************************************/") - fmt.Fprintf(w, "%sResult Init%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable);\n", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "%sResult Release%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable);\n", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "%sResult Load%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName);\n", NameSpace, NameSpace, NameSpace) + w.Writeln("%sResult Init%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable);", NameSpace, NameSpace, NameSpace) + w.Writeln("%sResult Release%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable);", NameSpace, NameSpace, NameSpace) + w.Writeln("%sResult Load%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName);", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "\n") + w.Writeln("") } - fmt.Fprintf(w, "#endif // __%s_DYNAMICHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("#endif // __%s_DYNAMICHEADER", strings.ToUpper(NameSpace)) + w.Writeln("") return nil } -func buildDynamicCInitTableCode(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string, spacing string) error { +func buildDynamicCInitTableCode(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { global := component.Global; - fmt.Fprintf(w, "%sif (pWrapperTable == nullptr)\n", spacing) - fmt.Fprintf(w, "%s return %s_ERROR_INVALIDPARAM;\n", spacing, strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%spWrapperTable->m_LibraryHandle = nullptr;\n", spacing) + w.Writeln("if (pWrapperTable == nullptr)") + w.Writeln(" return %s_ERROR_INVALIDPARAM;", strings.ToUpper(NameSpace)) + w.Writeln("") + w.Writeln("pWrapperTable->m_LibraryHandle = nullptr;") for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - fmt.Fprintf(w, "%spWrapperTable->m_%s_%s = nullptr;\n", spacing, class.ClassName, method.MethodName) + w.Writeln("pWrapperTable->m_%s_%s = nullptr;", class.ClassName, method.MethodName) } } global = component.Global for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - fmt.Fprintf(w, "%spWrapperTable->m_%s = nullptr;\n", spacing, method.MethodName) + w.Writeln("pWrapperTable->m_%s = nullptr;", method.MethodName) } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sreturn %s_SUCCESS;\n", spacing, strings.ToUpper(NameSpace)) + w.Writeln("") + w.Writeln("return %s_SUCCESS;", strings.ToUpper(NameSpace)) return nil; } -func buildDynamicCReleaseTableCode(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string, spacing string, initWrapperFunctionName string) error { +func buildDynamicCReleaseTableCode(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string, initWrapperFunctionName string) error { - fmt.Fprintf(w, "%sif (pWrapperTable == nullptr)\n", spacing) - fmt.Fprintf(w, "%s return %s_ERROR_INVALIDPARAM;\n", spacing, strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sif (pWrapperTable->m_LibraryHandle != nullptr) {\n", spacing) - fmt.Fprintf(w, "%s HMODULE hModule = (HMODULE) pWrapperTable->m_LibraryHandle;\n", spacing) - fmt.Fprintf(w, "%s FreeLibrary (hModule);\n", spacing) - fmt.Fprintf(w, "%s return %s (pWrapperTable);\n", spacing, initWrapperFunctionName) - fmt.Fprintf(w, "%s}\n", spacing) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sreturn %s_SUCCESS;\n", spacing, strings.ToUpper(NameSpace)) + w.Writeln("if (pWrapperTable == nullptr)") + w.Writeln(" return %s_ERROR_INVALIDPARAM;", strings.ToUpper(NameSpace)) + w.Writeln("") + w.Writeln("if (pWrapperTable->m_LibraryHandle != nullptr) {") + w.Writeln("#ifdef WIN32") + w.Writeln(" HMODULE hModule = (HMODULE) pWrapperTable->m_LibraryHandle;") + w.Writeln(" FreeLibrary (hModule);") + w.Writeln("#else // WIN32") + w.Writeln(" dlclose (pWrapperTable->m_LibraryHandle);") + w.Writeln("#endif // WIN32") + w.Writeln(" return %s (pWrapperTable);", initWrapperFunctionName) + w.Writeln("}") + w.Writeln("") + w.Writeln("return %s_SUCCESS;", strings.ToUpper(NameSpace)) return nil; } -func buildDynamicCLoadTableCode(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string, spacing string) error { +func buildDynamicCLoadTableCode(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { global := component.Global; - fmt.Fprintf(w, "%sif (pWrapperTable == nullptr)\n", spacing) - fmt.Fprintf(w, "%s return %s_ERROR_INVALIDPARAM;\n", spacing, strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "%sif (pLibraryFileName == nullptr)\n", spacing) - fmt.Fprintf(w, "%s return %s_ERROR_INVALIDPARAM;\n", spacing, strings.ToUpper(NameSpace)) + w.Writeln("if (pWrapperTable == nullptr)") + w.Writeln(" return %s_ERROR_INVALIDPARAM;", strings.ToUpper(NameSpace)) + w.Writeln("if (pLibraryFileName == nullptr)") + w.Writeln(" return %s_ERROR_INVALIDPARAM;", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("") - // TODO: Unicode - fmt.Fprintf(w, "%sHMODULE hLibrary = LoadLibraryA (pLibraryFileName);\n", spacing) - fmt.Fprintf(w, "%sif (hLibrary == 0) \n", spacing) - fmt.Fprintf(w, "%s return %s_ERROR_COULDNOTLOADLIBRARY;\n", spacing, strings.ToUpper(NameSpace)) + w.Writeln("#ifdef WIN32") + // TODO: Unicode + w.Writeln("HMODULE hLibrary = LoadLibraryA (pLibraryFileName);") + w.Writeln("if (hLibrary == 0) ") + w.Writeln(" return %s_ERROR_COULDNOTLOADLIBRARY;", strings.ToUpper(NameSpace)) + w.Writeln("#else // WIN32") + w.Writeln("void* hLibrary = dlopen (pLibraryFileName, RTLD_LAZY);") + w.Writeln("if (hLibrary == 0) ") + w.Writeln(" return %s_ERROR_COULDNOTLOADLIBRARY;", strings.ToUpper(NameSpace)) + w.Writeln("dlerror();"); + w.Writeln("#endif // WIN32") + w.Writeln("") + for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - - fmt.Fprintf(w, "%spWrapperTable->m_%s_%s = (P%s%s_%sPtr) GetProcAddress (hLibrary, \"%s_%s_%s%s\");\n", spacing, class.ClassName, method.MethodName, NameSpace, class.ClassName, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(class.ClassName), strings.ToLower(method.MethodName), method.DLLSuffix) - fmt.Fprintf(w, "%sif (pWrapperTable->m_%s_%s == nullptr)\n", spacing, class.ClassName, method.MethodName) - fmt.Fprintf(w, "%s return %s_ERROR_COULDNOTFINDLIBRARYEXPORT;\n", spacing, strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("#ifdef WIN32") + w.Writeln("pWrapperTable->m_%s_%s = (P%s%s_%sPtr) GetProcAddress (hLibrary, \"%s_%s_%s%s\");", class.ClassName, method.MethodName, NameSpace, class.ClassName, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(class.ClassName), strings.ToLower(method.MethodName), method.DLLSuffix) + w.Writeln("#else // WIN32") + w.Writeln("pWrapperTable->m_%s_%s = (P%s%s_%sPtr) dlsym (hLibrary, \"%s_%s_%s%s\");", class.ClassName, method.MethodName, NameSpace, class.ClassName, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(class.ClassName), strings.ToLower(method.MethodName), method.DLLSuffix) + w.Writeln("dlerror();") + w.Writeln("#endif // WIN32") + w.Writeln("if (pWrapperTable->m_%s_%s == nullptr)", class.ClassName, method.MethodName) + w.Writeln(" return %s_ERROR_COULDNOTFINDLIBRARYEXPORT;", strings.ToUpper(NameSpace)) + w.Writeln("") } } global = component.Global for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - - fmt.Fprintf(w, "%spWrapperTable->m_%s = (P%s%sPtr) GetProcAddress (hLibrary, \"%s_%s%s\");\n", spacing, method.MethodName, NameSpace, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(method.MethodName), method.DLLSuffix) - fmt.Fprintf(w, "%sif (pWrapperTable->m_%s == nullptr)\n", spacing, method.MethodName) - fmt.Fprintf(w, "%s return %s_ERROR_COULDNOTFINDLIBRARYEXPORT;\n", spacing, strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("#ifdef WIN32") + w.Writeln("pWrapperTable->m_%s = (P%s%sPtr) GetProcAddress (hLibrary, \"%s_%s%s\");", method.MethodName, NameSpace, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(method.MethodName), method.DLLSuffix) + w.Writeln("#else // WIN32") + w.Writeln("pWrapperTable->m_%s = (P%s%sPtr) dlsym (hLibrary, \"%s_%s%s\");", method.MethodName, NameSpace, method.MethodName, strings.ToLower(NameSpace), strings.ToLower(method.MethodName), method.DLLSuffix) + w.Writeln("dlerror();") + w.Writeln("#endif // WIN32") + + w.Writeln("if (pWrapperTable->m_%s == nullptr)", method.MethodName) + w.Writeln(" return %s_ERROR_COULDNOTFINDLIBRARYEXPORT;", strings.ToUpper(NameSpace)) + w.Writeln("") } - fmt.Fprintf(w, "%spWrapperTable->m_LibraryHandle = hLibrary;\n", spacing) - fmt.Fprintf(w, "%sreturn %s_SUCCESS;\n", spacing, strings.ToUpper(NameSpace)) + w.Writeln("pWrapperTable->m_LibraryHandle = hLibrary;") + w.Writeln("return %s_SUCCESS;", strings.ToUpper(NameSpace)) return nil; } -func buildDynamicCppImplementation(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string) error { +func buildDynamicCppImplementation(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { - fmt.Fprintf(w, "#include \"%s_types.h\"\n", BaseName) - fmt.Fprintf(w, "#include \"%s_dynamic.h\"\n", BaseName) - fmt.Fprintf(w, "#include <Windows.h>\n") + w.Writeln("#include \"%s_types.h\"", BaseName) + w.Writeln("#include \"%s_dynamic.h\"", BaseName) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sResult Init%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable)\n", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "{\n") - - buildDynamicCInitTableCode (component, w, NameSpace, BaseName, " "); - - fmt.Fprintf(w, "}\n") + w.Writeln("#ifdef WIN32") + w.Writeln("#include <Windows.h>") + w.Writeln("#else // WIN32") + w.Writeln("#include <dlfcn.h>") + w.Writeln("#endif // WIN32") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sResult Release%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable)\n", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "{\n") - - buildDynamicCReleaseTableCode (component, w, NameSpace, BaseName, " ", "Init" + NameSpace + "WrapperTable"); + w.Writeln("") + w.Writeln("%sResult Init%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable)", NameSpace, NameSpace, NameSpace) + w.Writeln("{") - fmt.Fprintf(w, "}\n") + w.AddIndentationLevel(1) + buildDynamicCInitTableCode(component, w, NameSpace, BaseName); + w.AddIndentationLevel(-1) + + w.Writeln("}") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "%sResult Load%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName)\n", NameSpace, NameSpace, NameSpace) - fmt.Fprintf(w, "{\n") + w.Writeln("") + w.Writeln("%sResult Release%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable)", NameSpace, NameSpace, NameSpace) + w.Writeln("{") - buildDynamicCLoadTableCode (component, w, NameSpace, BaseName, " "); + w.AddIndentationLevel(1) + buildDynamicCReleaseTableCode (component, w, NameSpace, BaseName, "Init" + NameSpace + "WrapperTable"); + w.AddIndentationLevel(-1) + + w.Writeln("}") + + w.Writeln("") + w.Writeln("%sResult Load%sWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName)", NameSpace, NameSpace, NameSpace) + w.Writeln("{") - fmt.Fprintf(w, "}\n") - fmt.Fprintf(w, "\n") + w.AddIndentationLevel(1) + buildDynamicCLoadTableCode (component, w, NameSpace, BaseName); + w.AddIndentationLevel(-1) + + w.Writeln("}") + w.Writeln("") return nil } -func writeDynamicCPPMethodDefinition(method ComponentDefinitionMethod, w io.Writer, NameSpace string, ClassName string, isGlobal bool) error { +func writeDynamicCPPMethodDefinition(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool) error { parameters := "" returntype := "void" @@ -343,14 +374,14 @@ func writeDynamicCPPMethodDefinition(method ComponentDefinitionMethod, w io.Writ } - fmt.Fprintf(w, " %s %s (%s);\n", returntype, method.MethodName, parameters); + w.Writeln(" %s %s (%s);", returntype, method.MethodName, parameters); return nil } -func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSpace string, ClassName string, isGlobal bool) error { +func writeDynamicCPPMethod(method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool) error { CMethodName := "" requiresInitCall := false; @@ -374,11 +405,11 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp parameters := "" returntype := "void" - definitionCode := ""; - functioncode := "" - returncode := "" - commentcode := "" - postCallCode := "" + definitionCodeLines := []string{} + functionCodeLines := []string{} + returnCodeLines := []string{} + commentcodeLines := []string{} + postCallCodeLines := []string{} cppClassPrefix := "C" + NameSpace cppClassName := cppClassPrefix + ClassName @@ -399,7 +430,7 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp } cppParamType := getBindingCppParamType(param, NameSpace, true) - commentcode = commentcode + fmt.Sprintf(" * @param[in] %s - %s\n", variableName, param.ParamDescription) + commentcodeLines = append(commentcodeLines, fmt.Sprintf("* @param[in] %s - %s", variableName, param.ParamDescription) ) switch param.ParamType { case "string": @@ -415,10 +446,10 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp initCallParameter = callParameter; parameters = parameters + fmt.Sprintf("const %s & %s", cppParamType, variableName); case "handle": - functioncode = functioncode + fmt.Sprintf(" %sHandle h%s = nullptr;\n", NameSpace, param.ParamName) - functioncode = functioncode + fmt.Sprintf(" if (%s != nullptr) {\n", variableName) - functioncode = functioncode + fmt.Sprintf(" h%s = %s->GetHandle ();\n", param.ParamName, variableName) - functioncode = functioncode + fmt.Sprintf(" };\n") + functionCodeLines = append(functionCodeLines, fmt.Sprintf("%sHandle h%s = nullptr;", NameSpace, param.ParamName)) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("if (%s != nullptr) {", variableName)) + functionCodeLines = append(functionCodeLines, fmt.Sprintf(" h%s = %s->GetHandle ();", param.ParamName, variableName)) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("};\n")) callParameter = "h" + param.ParamName; initCallParameter = callParameter; parameters = parameters + fmt.Sprintf("%s %s", cppParamType, variableName) @@ -431,7 +462,7 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp case "out": cppParamType := getBindingCppParamType(param, NameSpace, false) - commentcode = commentcode + fmt.Sprintf(" * @param[out] %s - %s\n", variableName, param.ParamDescription) + commentcodeLines = append(commentcodeLines, fmt.Sprintf("* @param[out] %s - %s", variableName, param.ParamDescription)) if parameters != "" { parameters = parameters + ", " @@ -442,32 +473,32 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp case "string": requiresInitCall = true; - definitionCode = definitionCode + fmt.Sprintf(" unsigned int bytesNeeded%s = 0;\n", param.ParamName) - definitionCode = definitionCode + fmt.Sprintf(" unsigned int bytesWritten%s = 0;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int bytesNeeded%s = 0;", param.ParamName)) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int bytesWritten%s = 0;", param.ParamName)) initCallParameter = fmt.Sprintf("0, &bytesNeeded%s, nullptr", param.ParamName); - functioncode = functioncode + fmt.Sprintf(" std::vector<char> buffer%s;\n", param.ParamName) - functioncode = functioncode + fmt.Sprintf(" buffer%s.resize(bytesNeeded%s + 2);\n", param.ParamName, param.ParamName) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("std::vector<char> buffer%s;", param.ParamName)) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("buffer%s.resize(bytesNeeded%s + 2);", param.ParamName, param.ParamName)) callParameter = fmt.Sprintf("bytesNeeded%s + 2, &bytesWritten%s, &buffer%s[0]", param.ParamName, param.ParamName, param.ParamName) - postCallCode = postCallCode + fmt.Sprintf(" buffer%s[bytesNeeded%s + 1] = 0;\n", param.ParamName, param.ParamName) + - fmt.Sprintf(" s%s = std::string(&buffer%s[0]);\n", param.ParamName, param.ParamName) + postCallCodeLines = append(postCallCodeLines, fmt.Sprintf("buffer%s[bytesNeeded%s + 1] = 0;", param.ParamName, param.ParamName) ) + postCallCodeLines = append(postCallCodeLines, fmt.Sprintf("s%s = std::string(&buffer%s[0]);", param.ParamName, param.ParamName) ) case "handle": // NOTTESTED - definitionCode = definitionCode + fmt.Sprintf(" %sHandle h%s = nullptr;\n", NameSpace, param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("%sHandle h%s = nullptr;", NameSpace, param.ParamName) ) callParameter = fmt.Sprintf("&h%s", param.ParamName) initCallParameter = callParameter; - postCallCode = postCallCode + fmt.Sprintf(" p%s = std::make_shared<%s%s> (h%s);\n", param.ParamName, cppClassPrefix, param.ParamClass, param.ParamName) + postCallCodeLines = append(postCallCodeLines, fmt.Sprintf("p%s = std::make_shared<%s%s> (h%s);", param.ParamName, cppClassPrefix, param.ParamClass, param.ParamName) ) case "structarray", "basicarray": requiresInitCall = true; - definitionCode = definitionCode + fmt.Sprintf(" unsigned int elementsNeeded%s = 0;\n", param.ParamName) - definitionCode = definitionCode + fmt.Sprintf(" unsigned int elementsWritten%s = 0;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int elementsNeeded%s = 0;", param.ParamName) ) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int elementsWritten%s = 0;", param.ParamName) ) initCallParameter = fmt.Sprintf("0, &elementsNeeded%s, nullptr", param.ParamName); - functioncode = functioncode + fmt.Sprintf(" %s.resize(elementsNeeded%s);\n", variableName, param.ParamName); + functionCodeLines = append(functionCodeLines, fmt.Sprintf("%s.resize(elementsNeeded%s);", variableName, param.ParamName)); callParameter = fmt.Sprintf("elementsNeeded%s, &elementsWritten%s, %s.data()", param.ParamName, param.ParamName, variableName) default: @@ -476,48 +507,47 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp } case "return": - - commentcode = commentcode + fmt.Sprintf(" * @return %s\n", param.ParamDescription) + commentcodeLines = append(commentcodeLines, fmt.Sprintf("* @return %s", param.ParamDescription) ) returntype = getBindingCppParamType(param, NameSpace, false) switch param.ParamType { case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double": callParameter = fmt.Sprintf("&result%s", param.ParamName) initCallParameter = callParameter; - definitionCode = definitionCode + fmt.Sprintf(" %s result%s = 0;\n", returntype, param.ParamName) - returncode = fmt.Sprintf(" return result%s;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("%s result%s = 0;\n", returntype, param.ParamName) ) + returnCodeLines = append(returnCodeLines, fmt.Sprintf("return result%s;", param.ParamName)) case "string": requiresInitCall = true; - definitionCode = definitionCode + fmt.Sprintf(" unsigned int bytesNeeded%s = 0;\n", param.ParamName) - definitionCode = definitionCode + fmt.Sprintf(" unsigned int bytesWritten%s = 0;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int bytesNeeded%s = 0;", param.ParamName)) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("unsigned int bytesWritten%s = 0;", param.ParamName)) initCallParameter = fmt.Sprintf("0, &bytesNeeded%s, nullptr", param.ParamName); - functioncode = functioncode + fmt.Sprintf(" std::vector<char> buffer%s;\n", param.ParamName) - functioncode = functioncode + fmt.Sprintf(" buffer%s.resize(bytesNeeded%s + 2);\n", param.ParamName, param.ParamName) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("std::vector<char> buffer%s;", param.ParamName)) + functionCodeLines = append(functionCodeLines, fmt.Sprintf("buffer%s.resize(bytesNeeded%s + 2);", param.ParamName, param.ParamName)) callParameter = fmt.Sprintf("bytesNeeded%s + 2, &bytesWritten%s, &buffer%s[0]", param.ParamName, param.ParamName, param.ParamName) - returncode = fmt.Sprintf(" buffer%s[bytesNeeded%s + 1] = 0;\n", param.ParamName, param.ParamName) + - fmt.Sprintf(" return std::string(&buffer%s[0]);\n", param.ParamName) + postCallCodeLines = append(postCallCodeLines, fmt.Sprintf("buffer%s[bytesNeeded%s + 1] = 0;", param.ParamName, param.ParamName)) + returnCodeLines = append(returnCodeLines, fmt.Sprintf("return std::string(&buffer%s[0]);", param.ParamName)) case "enum": callParameter = fmt.Sprintf("&result%s", param.ParamName) initCallParameter = callParameter; - definitionCode = definitionCode + fmt.Sprintf(" e%s%s result%s = (e%s%s) 0;\n", NameSpace, param.ParamClass, param.ParamName, NameSpace, param.ParamClass) - returncode = fmt.Sprintf(" return result%s;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("e%s%s result%s = (e%s%s) 0;", NameSpace, param.ParamClass, param.ParamName, NameSpace, param.ParamClass)) + returnCodeLines = append(returnCodeLines, fmt.Sprintf("return result%s;", param.ParamName)) case "struct": callParameter = fmt.Sprintf("&result%s", param.ParamName) initCallParameter = callParameter; - definitionCode = definitionCode + fmt.Sprintf(" s%s%s result%s;\n", NameSpace, param.ParamClass, param.ParamName) - returncode = fmt.Sprintf(" return result%s;\n", param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("s%s%s result%s;", NameSpace, param.ParamClass, param.ParamName)) + returnCodeLines = append(returnCodeLines, fmt.Sprintf("return result%s;", param.ParamName)) case "handle": - definitionCode = definitionCode + fmt.Sprintf(" %sHandle h%s = nullptr;\n", NameSpace, param.ParamName) + definitionCodeLines = append(definitionCodeLines, fmt.Sprintf("%sHandle h%s = nullptr;", NameSpace, param.ParamName)) callParameter = fmt.Sprintf("&h%s", param.ParamName) initCallParameter = callParameter; - returncode = fmt.Sprintf(" return std::make_shared<%s%s> (%sh%s);\n", cppClassPrefix, param.ParamClass, makeSharedParameter, param.ParamName) + returnCodeLines = append(returnCodeLines, fmt.Sprintf("return std::make_shared<%s%s> (%sh%s);", cppClassPrefix, param.ParamClass, makeSharedParameter, param.ParamName)) case "basicarray": return fmt.Errorf("can not return basicarray \"%s\" for %s.%s (%s)", param.ParamPass, ClassName, method.MethodName, param.ParamName) @@ -541,159 +571,162 @@ func writeDynamicCPPMethod(method ComponentDefinitionMethod, w io.Writer, NameSp initCallParameters = initCallParameters + ", "; } initCallParameters = initCallParameters + initCallParameter; - } - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * %s::%s - %s\n", cppClassName, method.MethodName, method.MethodDescription) - fmt.Fprintf(w, commentcode) - fmt.Fprintf(w, " */\n") + w.Writeln(" ") + w.Writeln(" /**") + w.Writeln(" * %s::%s - %s", cppClassName, method.MethodName, method.MethodDescription) + w.Writelns(" ", commentcodeLines) + w.Writeln(" */") if (isGlobal) { - fmt.Fprintf(w, " inline %s %s::%s (%s)\n", returntype, cppClassName, method.MethodName, parameters) + w.Writeln(" inline %s %s::%s (%s)", returntype, cppClassName, method.MethodName, parameters) } else { - fmt.Fprintf(w, " %s %s (%s)\n", returntype, method.MethodName, parameters) + w.Writeln(" %s %s (%s)", returntype, method.MethodName, parameters) } - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, definitionCode) + w.Writeln(" {") + w.Writelns(" ", definitionCodeLines) if (requiresInitCall) { - fmt.Fprintf(w, " %s %s (%s) );\n", checkErrorCode, CMethodName, initCallParameters) + w.Writeln(" %s %s (%s) );", checkErrorCode, CMethodName, initCallParameters) } - fmt.Fprintf(w, functioncode) - fmt.Fprintf(w, " %s %s (%s) );\n", checkErrorCode, CMethodName, callParameters) - fmt.Fprintf(w, postCallCode) - fmt.Fprintf(w, returncode) - fmt.Fprintf(w, " }\n") + w.Writelns(" ", functionCodeLines) + w.Writeln(" %s %s (%s) );", checkErrorCode, CMethodName, callParameters) + w.Writelns(" ", postCallCodeLines) + w.Writelns(" ", returnCodeLines) + w.Writeln(" }") return nil } -func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace string, BaseName string) error { +func buildDynamicCppHeader(component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { global := component.Global cppClassPrefix := "C" + NameSpace - fmt.Fprintf(w, "#ifndef __%s_DYNAMICCPPHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "#define __%s_DYNAMICCPPHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("#ifndef __%s_DYNAMICCPPHEADER", strings.ToUpper(NameSpace)) + w.Writeln("#define __%s_DYNAMICCPPHEADER", strings.ToUpper(NameSpace)) + w.Writeln("") - fmt.Fprintf(w, "#include \"%s_types.h\"\n", BaseName) - fmt.Fprintf(w, "#include \"%s_dynamic.h\"\n", BaseName) - fmt.Fprintf(w, "\n") + w.Writeln("#include \"%s_types.h\"", BaseName) + w.Writeln("#include \"%s_dynamic.h\"", BaseName) + w.Writeln("") - fmt.Fprintf(w, "#include <Windows.h>\n") - fmt.Fprintf(w, "#include <string>\n") - fmt.Fprintf(w, "#include <memory>\n") - fmt.Fprintf(w, "#include <vector>\n") - fmt.Fprintf(w, "#include <exception>\n") - fmt.Fprintf(w, "\n") + w.Writeln("#ifdef WIN32") + w.Writeln("#include <Windows.h>") + w.Writeln("#else // WIN32") + w.Writeln("#include <dlfcn.h>") + w.Writeln("#endif // WIN32") + w.Writeln("#include <string>") + w.Writeln("#include <memory>") + w.Writeln("#include <vector>") + w.Writeln("#include <exception>") + w.Writeln("") - fmt.Fprintf(w, "namespace %s {\n", NameSpace) - fmt.Fprintf(w, "\n") + w.Writeln("namespace %s {", NameSpace) + w.Writeln("") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Forward Declaration of all classes \n") - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - fmt.Fprintf(w, "\n") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Forward Declaration of all classes ") + w.Writeln("**************************************************************************************************************************/") + w.Writeln("") - fmt.Fprintf(w, "class %sBaseClass;\n", cppClassPrefix) - fmt.Fprintf(w, "class %sWrapper;\n", cppClassPrefix) + w.Writeln("class %sBaseClass;", cppClassPrefix) + w.Writeln("class %sWrapper;", cppClassPrefix) for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] - fmt.Fprintf(w, "class %s%s;\n", cppClassPrefix, class.ClassName) + w.Writeln("class %s%s;", cppClassPrefix, class.ClassName) } - fmt.Fprintf(w, "\n") + w.Writeln("") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Declaration of shared pointer types \n") - fmt.Fprintf(w, "**************************************************************************************************************************/\n") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Declaration of shared pointer types ") + w.Writeln("**************************************************************************************************************************/") - fmt.Fprintf(w, "\n") + w.Writeln("") - fmt.Fprintf(w, "typedef std::shared_ptr<%sBaseClass> P%sBaseClass;\n", cppClassPrefix, NameSpace) - fmt.Fprintf(w, "typedef std::shared_ptr<%sWrapper> P%sWrapper;\n", cppClassPrefix, NameSpace) + w.Writeln("typedef std::shared_ptr<%sBaseClass> P%sBaseClass;", cppClassPrefix, NameSpace) + w.Writeln("typedef std::shared_ptr<%sWrapper> P%sWrapper;", cppClassPrefix, NameSpace) for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] - fmt.Fprintf(w, "typedef std::shared_ptr<%s%s> P%s%s;\n", cppClassPrefix, class.ClassName, NameSpace, class.ClassName) + w.Writeln("typedef std::shared_ptr<%s%s> P%s%s;", cppClassPrefix, class.ClassName, NameSpace, class.ClassName) } - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Class E%sException \n", NameSpace) - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - fmt.Fprintf(w, "class E%sException : public std::runtime_error {\n", NameSpace) - fmt.Fprintf(w, " protected:\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * Error code for the Exception.\n") - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " %sResult m_errorcode;\n", NameSpace) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " public:\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * Exception Constructor.\n") - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " E%sException (%sResult errorcode)\n", NameSpace, NameSpace) - fmt.Fprintf(w, " : std::runtime_error (\"%s Error \" + std::to_string (errorcode))\n", NameSpace) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " m_errorcode = errorcode;\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * Returns error code\n") - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " %sResult getErrorCode ()\n", NameSpace) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " return m_errorcode;\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - - fmt.Fprintf(w, "};\n") - - fmt.Fprintf(w, " \n") - - - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Class %sWrapper \n", cppClassPrefix) - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - - fmt.Fprintf(w, "class %sWrapper {\n", cppClassPrefix) - fmt.Fprintf(w, "public:\n") - - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, " %sWrapper (const std::string &sFileName)\n", cppClassPrefix) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " CheckError (nullptr, initWrapperTable (&m_WrapperTable));\n") - fmt.Fprintf(w, " CheckError (nullptr, loadWrapperTable (&m_WrapperTable, sFileName.c_str ()));\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " \n") - - fmt.Fprintf(w, " static P%sWrapper loadLibrary (const std::string &sFileName)\n", NameSpace) - fmt.Fprintf(w, " {\n"); - fmt.Fprintf(w, " return std::make_shared<%sWrapper> (sFileName);\n", cppClassPrefix); - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " \n") - - - fmt.Fprintf(w, " ~%sWrapper ()\n", cppClassPrefix) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " releaseWrapperTable (&m_WrapperTable);\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " \n") - - fmt.Fprintf(w, " void CheckError(%sHandle handle, %sResult nResult)\n", NameSpace, NameSpace) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " if (nResult != 0) \n") - fmt.Fprintf(w, " throw E%sException (nResult);\n", NameSpace) - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " \n") - - fmt.Fprintf(w, "\n") + w.Writeln("") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Class E%sException ", NameSpace) + w.Writeln("**************************************************************************************************************************/") + w.Writeln("class E%sException : public std::runtime_error {", NameSpace) + w.Writeln("protected:") + w.Writeln(" /**") + w.Writeln(" * Error code for the Exception.") + w.Writeln(" */") + w.Writeln(" %sResult m_errorcode;", NameSpace) + w.Writeln("") + w.Writeln("public:") + w.Writeln(" /**") + w.Writeln(" * Exception Constructor.") + w.Writeln(" */") + w.Writeln(" E%sException (%sResult errorcode)", NameSpace, NameSpace) + w.Writeln(" : std::runtime_error (\"%s Error \" + std::to_string (errorcode))", NameSpace) + w.Writeln(" {") + w.Writeln(" m_errorcode = errorcode;") + w.Writeln(" }") + w.Writeln("") + w.Writeln(" /**") + w.Writeln(" * Returns error code") + w.Writeln(" */") + w.Writeln(" %sResult getErrorCode ()", NameSpace) + w.Writeln(" {") + w.Writeln(" return m_errorcode;") + w.Writeln(" }") + w.Writeln("") + + w.Writeln("};") + + w.Writeln("") + + + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Class %sWrapper ", cppClassPrefix) + w.Writeln("**************************************************************************************************************************/") + + w.Writeln("class %sWrapper {", cppClassPrefix) + w.Writeln("public:") + + w.Writeln(" ") + w.Writeln(" %sWrapper (const std::string &sFileName)", cppClassPrefix) + w.Writeln(" {") + w.Writeln(" CheckError (nullptr, initWrapperTable (&m_WrapperTable));") + w.Writeln(" CheckError (nullptr, loadWrapperTable (&m_WrapperTable, sFileName.c_str ()));") + w.Writeln(" }") + w.Writeln(" ") + + w.Writeln(" static P%sWrapper loadLibrary (const std::string &sFileName)", NameSpace) + w.Writeln(" {"); + w.Writeln(" return std::make_shared<%sWrapper> (sFileName);", cppClassPrefix); + w.Writeln(" }") + w.Writeln(" ") + + + w.Writeln(" ~%sWrapper ()", cppClassPrefix) + w.Writeln(" {") + w.Writeln(" releaseWrapperTable (&m_WrapperTable);") + w.Writeln(" }") + w.Writeln(" ") + + w.Writeln(" void CheckError(%sHandle handle, %sResult nResult)", NameSpace, NameSpace) + w.Writeln(" {") + w.Writeln(" if (nResult != 0) ") + w.Writeln(" throw E%sException (nResult);", NameSpace) + w.Writeln(" }") + w.Writeln(" ") + + w.Writeln("") for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] @@ -704,75 +737,75 @@ func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace } } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "private:\n") - fmt.Fprintf(w, " s%sDynamicWrapperTable m_WrapperTable;\n", NameSpace) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " %sResult initWrapperTable (s%sDynamicWrapperTable * pWrapperTable);\n", NameSpace, NameSpace) - fmt.Fprintf(w, " %sResult releaseWrapperTable (s%sDynamicWrapperTable * pWrapperTable);\n", NameSpace, NameSpace) - fmt.Fprintf(w, " %sResult loadWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName);\n", NameSpace, NameSpace) - fmt.Fprintf(w, "\n") + w.Writeln("") + w.Writeln("private:") + w.Writeln(" s%sDynamicWrapperTable m_WrapperTable;", NameSpace) + w.Writeln("") + w.Writeln(" %sResult initWrapperTable (s%sDynamicWrapperTable * pWrapperTable);", NameSpace, NameSpace) + w.Writeln(" %sResult releaseWrapperTable (s%sDynamicWrapperTable * pWrapperTable);", NameSpace, NameSpace) + w.Writeln(" %sResult loadWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName);", NameSpace, NameSpace) + w.Writeln("") for i := 0; i < len(component.Classes); i++ { class := component.Classes[i] cppClassName := cppClassPrefix + class.ClassName - fmt.Fprintf(w, " friend class %s;\n", cppClassName) + w.Writeln(" friend class %s;", cppClassName) } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, "};\n") - fmt.Fprintf(w, "\n") - - - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Class %sBaseClass \n", cppClassPrefix) - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - - fmt.Fprintf(w, "class %sBaseClass {\n", cppClassPrefix) - fmt.Fprintf(w, " protected:\n") - fmt.Fprintf(w, " /* Wrapper Object that created the class..*/\n") - fmt.Fprintf(w, " %sWrapper * m_pWrapper;\n", cppClassPrefix) - fmt.Fprintf(w, " /* Handle to Instance in library*/\n") - fmt.Fprintf(w, " %sHandle m_pHandle;\n", NameSpace) - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " /* Checks for an Error code and raises Exceptions */\n") - fmt.Fprintf(w, " void CheckError(%sResult nResult)\n", NameSpace) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " if (m_pWrapper != nullptr)\n") - fmt.Fprintf(w, " m_pWrapper->CheckError (m_pHandle, nResult);\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " public:\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * %sBaseClass::%sBaseClass - Constructor for Base class.\n", cppClassPrefix, cppClassPrefix) - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " %sBaseClass(%sWrapper * pWrapper, %sHandle pHandle)\n", cppClassPrefix, cppClassPrefix, NameSpace) - fmt.Fprintf(w, " : m_pWrapper (pWrapper), m_pHandle (pHandle)\n") - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * %sBaseClass::~%sBaseClass - Destructor for Base class.\n", cppClassPrefix, cppClassPrefix) - fmt.Fprintf(w, " */\n") - - fmt.Fprintf(w, " virtual ~%sBaseClass()\n", cppClassPrefix) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " if (m_pWrapper != nullptr)\n") - fmt.Fprintf(w, " m_pWrapper->%s (this);\n", component.Global.ReleaseMethod) - fmt.Fprintf(w, " m_pWrapper = nullptr;\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * %sBaseClass::GetHandle - Returns handle to instance.\n", cppClassPrefix) - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " %sHandle GetHandle()\n", NameSpace) - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " return m_pHandle;\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "};\n") - - fmt.Fprintf(w, " \n") + w.Writeln("") + w.Writeln("};") + w.Writeln("") + + + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Class %sBaseClass ", cppClassPrefix) + w.Writeln("**************************************************************************************************************************/") + + w.Writeln("class %sBaseClass {", cppClassPrefix) + w.Writeln("protected:") + w.Writeln(" /* Wrapper Object that created the class..*/") + w.Writeln(" %sWrapper * m_pWrapper;", cppClassPrefix) + w.Writeln(" /* Handle to Instance in library*/") + w.Writeln(" %sHandle m_pHandle;", NameSpace) + w.Writeln("") + w.Writeln(" /* Checks for an Error code and raises Exceptions */") + w.Writeln(" void CheckError(%sResult nResult)", NameSpace) + w.Writeln(" {") + w.Writeln(" if (m_pWrapper != nullptr)") + w.Writeln(" m_pWrapper->CheckError (m_pHandle, nResult);") + w.Writeln(" }") + w.Writeln("") + w.Writeln("public:") + w.Writeln("") + w.Writeln(" /**") + w.Writeln(" * %sBaseClass::%sBaseClass - Constructor for Base class.", cppClassPrefix, cppClassPrefix) + w.Writeln(" */") + w.Writeln(" %sBaseClass(%sWrapper * pWrapper, %sHandle pHandle)", cppClassPrefix, cppClassPrefix, NameSpace) + w.Writeln(" : m_pWrapper (pWrapper), m_pHandle (pHandle)") + w.Writeln(" {") + w.Writeln(" }") + w.Writeln("") + w.Writeln(" /**") + w.Writeln(" * %sBaseClass::~%sBaseClass - Destructor for Base class.", cppClassPrefix, cppClassPrefix) + w.Writeln(" */") + + w.Writeln(" virtual ~%sBaseClass()", cppClassPrefix) + w.Writeln(" {") + w.Writeln(" if (m_pWrapper != nullptr)") + w.Writeln(" m_pWrapper->%s (this);", component.Global.ReleaseMethod) + w.Writeln(" m_pWrapper = nullptr;") + w.Writeln(" }") + w.Writeln("") + w.Writeln(" /**") + w.Writeln(" * %sBaseClass::GetHandle - Returns handle to instance.", cppClassPrefix) + w.Writeln(" */") + w.Writeln(" %sHandle GetHandle()", NameSpace) + w.Writeln(" {") + w.Writeln(" return m_pHandle;") + w.Writeln(" }") + w.Writeln("};") + + w.Writeln(" ") for i := 0; i < len(component.Classes); i++ { @@ -785,21 +818,21 @@ func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace } cppParentClassName := cppClassPrefix + parentClassName - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, "/*************************************************************************************************************************\n") - fmt.Fprintf(w, " Class %s \n", cppClassName) - fmt.Fprintf(w, "**************************************************************************************************************************/\n") - fmt.Fprintf(w, "class %s : public %s {\n", cppClassName, cppParentClassName) - fmt.Fprintf(w, " public:\n") - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, " /**\n") - fmt.Fprintf(w, " * %s::%s - Constructor for %s class.\n", cppClassName, cppClassName, class.ClassName) - fmt.Fprintf(w, " */\n") - fmt.Fprintf(w, " %s (%sWrapper * pWrapper, %sHandle pHandle)\n", cppClassName, cppClassPrefix, NameSpace) - fmt.Fprintf(w, " : %s (pWrapper, pHandle)\n", cppParentClassName); - fmt.Fprintf(w, " {\n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, " \n") + w.Writeln(" ") + w.Writeln("/*************************************************************************************************************************") + w.Writeln(" Class %s ", cppClassName) + w.Writeln("**************************************************************************************************************************/") + w.Writeln("class %s : public %s {", cppClassName, cppParentClassName) + w.Writeln("public:") + w.Writeln(" ") + w.Writeln(" /**") + w.Writeln(" * %s::%s - Constructor for %s class.", cppClassName, cppClassName, class.ClassName) + w.Writeln(" */") + w.Writeln(" %s (%sWrapper * pWrapper, %sHandle pHandle)", cppClassName, cppClassPrefix, NameSpace) + w.Writeln(" : %s (pWrapper, pHandle)", cppParentClassName); + w.Writeln(" {") + w.Writeln(" }") + w.Writeln(" ") for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] @@ -808,11 +841,8 @@ func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace if err != nil { return err } - } - - fmt.Fprintf(w, "};\n\n") - + w.Writeln("};\n") } @@ -825,37 +855,42 @@ func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace } } - fmt.Fprintf(w, "\n") - fmt.Fprintf(w, " inline %sResult %sWrapper::initWrapperTable (s%sDynamicWrapperTable * pWrapperTable)\n", NameSpace, cppClassPrefix, NameSpace) - fmt.Fprintf(w, " {\n") - - buildDynamicCInitTableCode (component, w, NameSpace, BaseName, " "); + w.Writeln("") + w.Writeln(" inline %sResult %sWrapper::initWrapperTable (s%sDynamicWrapperTable * pWrapperTable)", NameSpace, cppClassPrefix, NameSpace) + w.Writeln(" {") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") + w.AddIndentationLevel(2) + buildDynamicCInitTableCode (component, w, NameSpace, BaseName); + w.AddIndentationLevel(-2) - fmt.Fprintf(w, " inline %sResult %sWrapper::releaseWrapperTable (s%sDynamicWrapperTable * pWrapperTable)\n", NameSpace, cppClassPrefix, NameSpace) - fmt.Fprintf(w, " {\n") + w.Writeln(" }") + w.Writeln("") - buildDynamicCReleaseTableCode (component, w, NameSpace, BaseName, " ", "initWrapperTable"); + w.Writeln(" inline %sResult %sWrapper::releaseWrapperTable (s%sDynamicWrapperTable * pWrapperTable)", NameSpace, cppClassPrefix, NameSpace) + w.Writeln(" {") - fmt.Fprintf(w, " \n") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") - - fmt.Fprintf(w, " inline %sResult %sWrapper::loadWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName)\n", NameSpace, cppClassPrefix, NameSpace) - fmt.Fprintf(w, " {\n") + w.AddIndentationLevel(2) + buildDynamicCReleaseTableCode (component, w, NameSpace, BaseName, "initWrapperTable"); + w.AddIndentationLevel(-2) + + w.Writeln(" }") + w.Writeln("") - buildDynamicCLoadTableCode (component, w, NameSpace, BaseName, " "); + w.Writeln(" inline %sResult %sWrapper::loadWrapperTable (s%sDynamicWrapperTable * pWrapperTable, const char * pLibraryFileName)", NameSpace, cppClassPrefix, NameSpace) + w.Writeln(" {") - fmt.Fprintf(w, " }\n") - fmt.Fprintf(w, "\n") + w.AddIndentationLevel(2) + buildDynamicCLoadTableCode (component, w, NameSpace, BaseName); + w.AddIndentationLevel(-2) + + w.Writeln(" }") + w.Writeln("") - fmt.Fprintf(w, "} // namespace %s\n", NameSpace) - fmt.Fprintf(w, "\n") + w.Writeln("} // namespace %s", NameSpace) + w.Writeln("") - fmt.Fprintf(w, "#endif // __%s_DYNAMICCPPHEADER\n", strings.ToUpper(NameSpace)) - fmt.Fprintf(w, "\n") + w.Writeln("#endif // __%s_DYNAMICCPPHEADER", strings.ToUpper(NameSpace)) + w.Writeln("") return nil } @@ -864,7 +899,7 @@ func buildDynamicCppHeader(component ComponentDefinition, w io.Writer, NameSpace // BuildBindingCppDynamic builds dynamic headeronly C++-bindings of a library's API in form of dynamically loaded functions // handles. -func BuildBindingCppDynamic(component ComponentDefinition, outputFolder string, outputFolderExample string) error { +func BuildBindingCppDynamic(component ComponentDefinition, outputFolder string, outputFolderExample string, indentString string) error { forceRecreation := false namespace := component.NameSpace; @@ -873,11 +908,11 @@ func BuildBindingCppDynamic(component ComponentDefinition, outputFolder string, DynamicCHeader := path.Join(outputFolder, baseName+"_dynamic.h"); log.Printf("Creating \"%s\"", DynamicCHeader) - dynhfile, err := os.Create(DynamicCHeader) + dynhfile, err := CreateLanguageFile(DynamicCHeader, indentString) if err != nil { return err; } - WriteLicenseHeader(dynhfile, component, + dynhfile.WriteCLicenseHeader(component, fmt.Sprintf("This is an autogenerated plain C Header file in order to allow an easy\n use of %s", libraryname), true) err = buildDynamicCHeader(component, dynhfile, namespace, baseName, true) @@ -887,11 +922,11 @@ func BuildBindingCppDynamic(component ComponentDefinition, outputFolder string, DynamicCppHeader := path.Join(outputFolder, baseName+"_dynamic.hpp"); log.Printf("Creating \"%s\"", DynamicCppHeader) - dynhppfile, err := os.Create(DynamicCppHeader) + dynhppfile, err := CreateLanguageFile(DynamicCppHeader, indentString) if err != nil { return err; } - WriteLicenseHeader(dynhppfile, component, + dynhppfile.WriteCLicenseHeader(component, fmt.Sprintf("This is an autogenerated C++ Header file in order to allow an easy\n use of %s", libraryname), true) err = buildDynamicCppHeader(component, dynhppfile, namespace, baseName) @@ -969,11 +1004,15 @@ func buildBDynamicCppExample(componentdefinition ComponentDefinition, w Language func buildBDynamicCppExampleCMake(componentdefinition ComponentDefinition, w LanguageWriter, outputFolder string) error { NameSpace := componentdefinition.NameSpace - w.Writeln("cmake_minimum_required(VERSION 3.11)") + w.Writeln("cmake_minimum_required(VERSION 3.5)") w.Writeln("") w.Writeln("project(%sExample_CPPDynamic)", NameSpace) + w.Writeln("set (CMAKE_CXX_STANDARD 11)") w.Writeln("add_executable(%sExample_CPPDynamic \"${CMAKE_CURRENT_SOURCE_DIR}/%s_example.cpp\")", NameSpace, NameSpace) + w.Writeln("if (UNIX)") + w.Writeln(" target_link_libraries(%sExample_CPPDynamic ${CMAKE_DL_LIBS})", NameSpace) + w.Writeln("endif (UNIX)") // TODO: calculate relative path from ExampleOutputFolder to OUTPUTFOLDER based on CURRENT_SOURCE_DIR outputFolder = strings.Replace(outputFolder, string(filepath.Separator), "/", -1) w.Writeln("target_include_directories(%sExample_CPPDynamic PRIVATE \"%s\")", NameSpace, outputFolder) diff --git a/Source/buildbindingpascal.go b/Source/buildbindingpascal.go index a467a07d..bce9f970 100644 --- a/Source/buildbindingpascal.go +++ b/Source/buildbindingpascal.go @@ -102,178 +102,73 @@ func BuildBindingPascalDynamic(componentdefinition ComponentDefinition, outputFo } +func writeEnumConversionInterface(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string) error { -func writePascalBaseTypeDefinitions(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { - - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" General type definitions"); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln ("") - - w.Writeln ("type"); - w.Writeln (" T%sResult = Cardinal;", NameSpace); - w.Writeln (" T%sHandle = Pointer;", NameSpace); - w.Writeln ("") - - w.Writeln (" P%sResult = ^T%sResult;", NameSpace, NameSpace); - w.Writeln (" P%sHandle = ^T%sHandle;", NameSpace, NameSpace); - w.Writeln ("") - - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Error Constants for %s", NameSpace); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln (""); - w.Writeln ("const"); - w.Writeln (" %s_SUCCESS = 0;", strings.ToUpper (NameSpace)); - - for i := 0; i < len(componentdefinition.Errors.Errors); i++ { - errorcode := componentdefinition.Errors.Errors[i]; - w.Writeln (" %s_ERROR_%s = %d;", strings.ToUpper (NameSpace), errorcode.Name, errorcode.Code); - } - - w.Writeln (""); - - if (len(componentdefinition.Enums) > 0) { w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Declaration of enums"); + w.Writeln (" Enum conversion"); w.Writeln ("**************************************************************************************************************************)"); w.Writeln (""); - w.Writeln ("type"); - w.Writeln (""); for i := 0; i < len(componentdefinition.Enums); i++ { enum := componentdefinition.Enums[i]; - w.Writeln (" T%s%s = (", NameSpace, enum.Name); - - for j := 0; j < len(enum.Options); j++ { - - comma := ""; - if (j < len(enum.Options) - 1) { - comma = ","; - } - - - option := enum.Options[j]; - w.Writeln (" e%s%s%s", enum.Name, option.Name, comma); - } - - w.Writeln ( " );"); - w.Writeln ( ""); + w.Writeln (" function convert%sToConst (const AValue: T%s%s): Integer;", enum.Name, NameSpace, enum.Name); + w.Writeln (" function convertConstTo%s (const AValue: Integer): T%s%s;", enum.Name, NameSpace, enum.Name); } + + w.Writeln (""); } - - if len(componentdefinition.Structs) > 0 { + return nil; +} + + +func writeEnumConversionImplementation(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string) error { + + + if (len(componentdefinition.Enums) > 0) { w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Declaration of structs"); + w.Writeln (" Enum conversion"); w.Writeln ("**************************************************************************************************************************)"); w.Writeln (""); - w.Writeln ("type"); - w.Writeln (""); - - for i := 0; i < len(componentdefinition.Structs); i++ { - structinfo := componentdefinition.Structs[i]; - w.Writeln ( " P%s%s = ^T%s%s;", NameSpace, structinfo.Name, NameSpace, structinfo.Name); - w.Writeln ( " T%s%s = packed record", NameSpace, structinfo.Name); - - for j := 0; j < len(structinfo.Members); j++ { - element := structinfo.Members[j]; - - arrayprefix := ""; - if (element.Rows > 0) { - if (element.Columns > 0) { - arrayprefix = fmt.Sprintf ("array [0..%d, 0..%d] of ", element.Columns - 1, element.Rows - 1) - } else { - arrayprefix = fmt.Sprintf ("array [0..%d] of ",element.Rows - 1) - } - } + for i := 0; i < len(componentdefinition.Enums); i++ { + enum := componentdefinition.Enums[i]; + w.Writeln (" function convert%sToConst (const AValue: T%s%s): Integer;", enum.Name, NameSpace, enum.Name); + w.Writeln (" begin"); + w.Writeln (" case AValue of"); - switch (element.Type) { - case "uint8": - w.Writeln ( " F%s: %sByte;", element.Name, arrayprefix); - case "uint16": - w.Writeln ( " F%s: %sWord;", element.Name, arrayprefix); - case "uint32": - w.Writeln ( " F%s: %sCardinal;", element.Name, arrayprefix); - case "uint64": - w.Writeln ( " F%s: %sQWord;", element.Name, arrayprefix); - case "int8": - w.Writeln ( " F%s: %sSmallInt;", element.Name, arrayprefix); - case "int16": - w.Writeln ( " F%s: %sShortInt;", element.Name, arrayprefix); - case "int32": - w.Writeln ( " F%s: %sInteger;", element.Name, arrayprefix); - case "int64": - w.Writeln ( " F%s: %sInt64;", element.Name, arrayprefix); - case "bool": - w.Writeln ( " F%s: %sCardinal;", element.Name, arrayprefix); - case "single": - w.Writeln ( " F%s: %sSingle;", element.Name, arrayprefix); - case "double": - w.Writeln ( " F%s: %sDouble;", element.Name, arrayprefix); - case "string": - return fmt.Errorf ("it is not possible for struct s%s%s to contain a string value", NameSpace, structinfo.Name); - case "handle": - return fmt.Errorf ("it is not possible for struct s%s%s to contain a handle value", NameSpace, structinfo.Name); - case "enum": - w.Writeln ( " F%s: %sInteger;", element.Name, arrayprefix); - } - - + for j := 0; j < len(enum.Options); j++ { + option := enum.Options[j]; + w.Writeln (" e%s%s: Result := %d;", enum.Name, option.Name, option.Value); } + w.Writeln (" else "); + w.Writeln (" raise E%sException.CreateCustomMessage (%s_ERROR_INVALIDPARAM, 'invalid enum value');", NameSpace, strings.ToUpper (NameSpace)); + w.Writeln (" end;"); w.Writeln (" end;"); - w.Writeln (""); - } - - w.Writeln ( ""); - - if len(componentdefinition.Functions) > 0 { - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Declaration of function types"); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln (""); - for i := 0; i < len(componentdefinition.Functions); i++ { - funcinfo := componentdefinition.Functions[i]; - arguments := "" - for j := 0; j<len(funcinfo.Params); j++ { - param := funcinfo.Params[j] - if (arguments != "") { - arguments = arguments + "; " - } - cParams, err := generatePlainPascalParameter(param, "", funcinfo.FunctionName, NameSpace) - if (err != nil) { - return err - } - arguments = arguments + cParams[0].ParamConvention + cParams[0].ParamName + ": " + cParams[0].ParamType - } - - w.Writeln (" P%s_%s = function(%s): Integer;", NameSpace, funcinfo.FunctionName, arguments); + w.Writeln (" "); + w.Writeln (" function convertConstTo%s (const AValue: Integer): T%s%s;", enum.Name, NameSpace, enum.Name); + w.Writeln (" begin"); + w.Writeln (" case AValue of"); + + for j := 0; j < len(enum.Options); j++ { + option := enum.Options[j]; + w.Writeln (" %d: Result := e%s%s;", option.Value, enum.Name, option.Name); } - } - - w.Writeln ( ""); - - - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Declaration of struct arrays"); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln (""); - for i := 0; i < len(componentdefinition.Structs); i++ { - structinfo := componentdefinition.Structs[i]; - w.Writeln (" ArrayOf%s%s = array of T%s%s;", NameSpace, structinfo.Name, NameSpace, structinfo.Name); + w.Writeln (" else "); + w.Writeln (" raise E%sException.CreateCustomMessage (%s_ERROR_INVALIDPARAM, 'invalid enum constant');", NameSpace, strings.ToUpper (NameSpace)); + w.Writeln (" end;"); + w.Writeln (" end;"); + w.Writeln (" "); + w.Writeln (" "); } - + w.Writeln (""); - } - - return nil; - + return nil; } @@ -347,11 +242,9 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w if err != nil { return err; } - } - w.Writeln ("(*************************************************************************************************************************"); w.Writeln (" Exception definition"); w.Writeln ("**************************************************************************************************************************)"); @@ -415,7 +308,6 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w w.Writeln (" end;"); w.Writeln ("") - } @@ -426,7 +318,6 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w w.Writeln (" T%sWrapper = class (TObject)", NameSpace); w.Writeln (" private"); w.Writeln (" FModule: HMODULE;"); - for i := 0; i < len(componentdefinition.Classes); i++ { class := componentdefinition.Classes[i] @@ -436,14 +327,12 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w w.Writeln (" F%s%s_%sFunc: T%s%s_%sFunc;", NameSpace, class.ClassName, method.MethodName, NameSpace, class.ClassName, method.MethodName); } - } for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - + w.Writeln (" F%s%sFunc: T%s%sFunc;", NameSpace, method.MethodName, NameSpace, method.MethodName); - } w.Writeln ("") @@ -496,67 +385,15 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w w.Writeln ("") - if (len(componentdefinition.Enums) > 0) { - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Enum conversion"); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln (""); - - for i := 0; i < len(componentdefinition.Enums); i++ { - enum := componentdefinition.Enums[i]; - w.Writeln (" function convert%sToConst (const AValue: T%s%s): Integer;", enum.Name, NameSpace, enum.Name); - w.Writeln (" function convertConstTo%s (const AValue: Integer): T%s%s;", enum.Name, NameSpace, enum.Name); - } - - w.Writeln (""); - } + writeEnumConversionInterface (componentdefinition, w, NameSpace); + w.Writeln ("") w.Writeln ("implementation") w.Writeln ("") - - if (len(componentdefinition.Enums) > 0) { - w.Writeln ("(*************************************************************************************************************************"); - w.Writeln (" Enum conversion"); - w.Writeln ("**************************************************************************************************************************)"); - w.Writeln (""); - for i := 0; i < len(componentdefinition.Enums); i++ { - enum := componentdefinition.Enums[i]; - w.Writeln (" function convert%sToConst (const AValue: T%s%s): Integer;", enum.Name, NameSpace, enum.Name); - w.Writeln (" begin"); - w.Writeln (" case AValue of"); - - for j := 0; j < len(enum.Options); j++ { - option := enum.Options[j]; - w.Writeln (" e%s%s: Result := %d;", enum.Name, option.Name, option.Value); - } - - w.Writeln (" else "); - w.Writeln (" raise E%sException.CreateCustomMessage (%s_ERROR_INVALIDPARAM, 'invalid enum value');", NameSpace, strings.ToUpper (NameSpace)); - w.Writeln (" end;"); - w.Writeln (" end;"); - w.Writeln (" "); - w.Writeln (" function convertConstTo%s (const AValue: Integer): T%s%s;", enum.Name, NameSpace, enum.Name); - w.Writeln (" begin"); - w.Writeln (" case AValue of"); - - for j := 0; j < len(enum.Options); j++ { - option := enum.Options[j]; - w.Writeln (" %d: Result := e%s%s;", option.Value, enum.Name, option.Name); - } - - w.Writeln (" else "); - w.Writeln (" raise E%sException.CreateCustomMessage (%s_ERROR_INVALIDPARAM, 'invalid enum constant');", NameSpace, strings.ToUpper (NameSpace)); - w.Writeln (" end;"); - w.Writeln (" end;"); - w.Writeln (" "); - w.Writeln (" "); - } + writeEnumConversionImplementation (componentdefinition, w, NameSpace); - w.Writeln (""); - } - w.Writeln ("") w.Writeln ("(*************************************************************************************************************************"); w.Writeln (" Exception implementation"); @@ -740,125 +577,13 @@ func buildDynamicPascalImplementation(componentdefinition ComponentDefinition, w return nil } - - -func getPascalParameterTypeName(ParamTypeName string, NameSpace string, ParamClass string, isPlain bool, isImplementation bool)(string, error) { - PascalParamTypeName := ""; - switch (ParamTypeName) { - case "uint8": - PascalParamTypeName = "Byte"; - - case "uint16": - PascalParamTypeName = "Word"; - - case "uint32": - PascalParamTypeName = "Cardinal"; - - case "uint64": - PascalParamTypeName = "QWord"; - - case "int8": - PascalParamTypeName = "ShortInt"; - - case "int16": - PascalParamTypeName = "SmallInt"; - - case "int32": - PascalParamTypeName = "Integer"; - - case "int64": - PascalParamTypeName = "Int64"; - - case "bool": - if isPlain { - PascalParamTypeName = "Cardinal"; - } else { - PascalParamTypeName = "Boolean"; - } - - case "single": - PascalParamTypeName = "Single"; - - case "double": - PascalParamTypeName = "Double"; - - case "string": - if isPlain { - PascalParamTypeName = "PAnsiChar"; - } else { - PascalParamTypeName = "String"; - } - - case "enum": - if isPlain { - PascalParamTypeName = fmt.Sprintf ("Integer"); - } else { - PascalParamTypeName = fmt.Sprintf ("T%s%s", NameSpace, ParamClass); - } - - case "functiontype": - if isPlain { - PascalParamTypeName = fmt.Sprintf ("P%s_%s", NameSpace, ParamClass); - } else { - PascalParamTypeName = fmt.Sprintf ("P%s_%s", NameSpace, ParamClass); - } - - case "struct": - PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass); - - case "basicarray": - basicTypeName, err := getPascalParameterTypeName(ParamClass, NameSpace, "", isPlain, isImplementation); - if (err != nil) { - return "", err; - } - - if isPlain { - PascalParamTypeName = fmt.Sprintf ("P%s", basicTypeName); - } else { - if isImplementation { - PascalParamTypeName = fmt.Sprintf ("P%s", basicTypeName); - } else { - PascalParamTypeName = fmt.Sprintf ("T%sDynArray", basicTypeName); - } - } - - case "structarray": - if isPlain { - PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass) - } else { - if isImplementation { - PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass) - } else { - PascalParamTypeName = fmt.Sprintf ("ArrayOf%s%s", NameSpace, ParamClass); - } - } - - case "handle": - if isPlain { - PascalParamTypeName = fmt.Sprintf ("T%sHandle", NameSpace) - } else { - if isImplementation { - PascalParamTypeName = "TObject"; - } else { - PascalParamTypeName = fmt.Sprintf ("T%s%s", NameSpace, ParamClass); - } - } - - default: - return "", fmt.Errorf ("invalid parameter type \"%s\" for Pascal parameter", ParamTypeName); - } - - return PascalParamTypeName, nil; -} - func getPascalClassParameters(method ComponentDefinitionMethod, NameSpace string, ClassName string, isGlobal bool, isImplementation bool) (string, string, error) { - parameters := ""; returnType := ""; for k := 0; k < len(method.Params); k++ { param := method.Params [k]; - ParamTypeName, err := getPascalParameterTypeName (param.ParamType, NameSpace, param.ParamClass, false, isImplementation); + ParamTypeName, err := getPascalParameterType(param.ParamType, NameSpace, param.ParamClass, false, isImplementation); if err != nil { return "", "", err; } @@ -868,28 +593,22 @@ func getPascalClassParameters(method ComponentDefinitionMethod, NameSpace string if (parameters != "") { parameters = parameters + "; "; } - parameters = parameters + "const A" + param.ParamName + ": " + ParamTypeName; case "out": if (parameters != "") { parameters = parameters + "; "; } - parameters = parameters + "out A" + param.ParamName + ": " + ParamTypeName; - case "return": if (returnType != "") { return "", "", fmt.Errorf ("duplicate return value \"%s\" for Pascal method \"%s\"", param.ParamName, method.MethodName); } - returnType = ParamTypeName; - } } - return parameters, returnType, nil; } @@ -901,11 +620,16 @@ func writePascalClassMethodDefinition (method ComponentDefinitionMethod, w Langu if (err != nil) { return err; } + + classPrefix := ""; + if (isImplementation && isGlobal) { + classPrefix = "class "; + } if (returnType == "") { - w.Writeln ( spacing + "procedure %s(%s);", method.MethodName, parameters); + w.Writeln ( spacing + "%sprocedure %s(%s);", classPrefix, method.MethodName, parameters); } else { - w.Writeln ( spacing + "function %s(%s): %s;", method.MethodName, parameters, returnType); + w.Writeln ( spacing + "%sfunction %s(%s): %s;", classPrefix, method.MethodName, parameters, returnType); } return nil; @@ -952,7 +676,7 @@ func writePascalClassMethodImplementation (method ComponentDefinitionMethod, w L for k := 0; k < len(method.Params); k++ { param := method.Params [k]; - PlainParamTypeName, err := getPascalParameterTypeName (param.ParamType, NameSpace, param.ParamClass, true, false); + PlainParamTypeName, err := getPascalParameterType(param.ParamType, NameSpace, param.ParamClass, true, false); if err != nil { return err; } @@ -990,7 +714,7 @@ func writePascalClassMethodImplementation (method ComponentDefinitionMethod, w L initCallParameters = initCallParameters + "@A" + param.ParamName; case "basicarray": - basicPlainTypeName, err := getPascalParameterTypeName(param.ParamClass, NameSpace, "", true, false); + basicPlainTypeName, err := getPascalParameterType(param.ParamClass, NameSpace, "", true, false); if err != nil { return err; } @@ -1273,291 +997,6 @@ func writePascalFunctionType (method ComponentDefinitionMethod, w LanguageWriter -type pascalParameter struct { - ParamType string - ParamName string - ParamComment string - ParamConvention string - ParamTypeNoConvention string -} - - -func generatePlainPascalParameter(param ComponentDefinitionParam, className string, methodName string, NameSpace string) ([]pascalParameter, error) { - cParams := make([]pascalParameter,1) - cParamTypeName, err := getPascalParameterTypeName(param.ParamType, NameSpace, param.ParamClass, true, false); - if (err != nil) { - return nil, err; - } - - switch (param.ParamPass) { - case "in": - switch (param.ParamType) { - case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "n" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "bool": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "b" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "single": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "f" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "double": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "d" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "string": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "enum": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "e" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "struct": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "basicarray", "structarray": - cParams = make([]pascalParameter,2) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "Count"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = cParamTypeName; - cParams[1].ParamName = "p" + param.ParamName + "Buffer"; - cParams[1].ParamComment = fmt.Sprintf("* @param[in] %s - %s buffer of %s", cParams[1].ParamName, param.ParamClass, param.ParamDescription); - cParams[1].ParamConvention = "const "; - cParams[1].ParamTypeNoConvention = cParams[1].ParamType; - - case "functiontype": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - case "handle": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - default: - return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); - } - - case "out": - - switch (param.ParamType) { - - case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double", "enum": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName; - - case "struct": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; - - case "basicarray": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "Count"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = cParamTypeName; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "structarray": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "Count"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = cParamTypeName; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "string": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - size of the buffer (including trailing 0)", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededChars"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written bytes, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = "PAnsiChar"; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s, may be NULL", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "handle": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; - - default: - return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); - } - - case "return": - - switch (param.ParamType) { - - case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double", "enum": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName; - - case "struct": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; - - case "basicarray": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "Count"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = cParamTypeName; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "structarray": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "Count"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = cParamTypeName; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "string": - cParams = make([]pascalParameter,3) - cParams[0].ParamType = "Cardinal"; - cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; - cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - size of the buffer (including trailing 0)", cParams[0].ParamName); - cParams[0].ParamConvention = "const "; - cParams[0].ParamTypeNoConvention = cParams[0].ParamType; - - cParams[1].ParamType = "Cardinal"; - cParams[1].ParamName = "p" + param.ParamName + "NeededChars"; - cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written bytes, or needed buffer size.", cParams[1].ParamName); - cParams[1].ParamConvention = "out "; - cParams[1].ParamTypeNoConvention = "PCardinal"; - - cParams[2].ParamType = "PAnsiChar"; - cParams[2].ParamName = "p" + param.ParamName + "Buffer"; - cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s, may be NULL", cParams[2].ParamName, param.ParamClass, param.ParamDescription); - cParams[2].ParamConvention = ""; - cParams[2].ParamTypeNoConvention = cParams[2].ParamType; - - case "handle": - cParams[0].ParamType = cParamTypeName; - cParams[0].ParamName = "p" + param.ParamName; - cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); - cParams[0].ParamConvention = "out "; - cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; - - default: - return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); - } - - default: - return nil, fmt.Errorf ("invalid method parameter passing \"%s\" for %s.%s (%s)", param.ParamPass, className, methodName, param.ParamName); - } - - return cParams, nil; -} - func generatePlainPascalParameters(method ComponentDefinitionMethod, className string, NameSpace string) ([]pascalParameter, error) { parameters := []pascalParameter{}; for k := 0; k < len(method.Params); k++ { diff --git a/Source/buildimplementationcpp.go b/Source/buildimplementationcpp.go index e2c96c59..f72db9cc 100644 --- a/Source/buildimplementationcpp.go +++ b/Source/buildimplementationcpp.go @@ -1282,13 +1282,15 @@ func generateJournalFunctionCode (method ComponentDefinitionMethod, NameSpace st func buildCMakeForCPPImplementation(component ComponentDefinition, w LanguageWriter, doJournal bool) { NameSpace := component.NameSpace - w.Writeln("cmake_minimum_required(VERSION 3.11)") + w.Writeln("cmake_minimum_required(VERSION 3.5)") w.Writeln("") w.Writeln("### The implementation of the %s component", component.LibraryName) w.Writeln("project(%s)", NameSpace) w.Writeln("") - + w.Writeln("set (CMAKE_CXX_STANDARD 11)") + w.Writeln("") + w.Writeln("# The location of autogenerated interfaces") w.Writeln("set(CMAKE_CURRENT_AUTOGENERATED_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Interfaces)",) w.Writeln("") diff --git a/Source/buildimplementationpascal.go b/Source/buildimplementationpascal.go index d51a1bfa..26a46bb2 100644 --- a/Source/buildimplementationpascal.go +++ b/Source/buildimplementationpascal.go @@ -37,6 +37,7 @@ package main import ( "fmt" "log" + "errors" "path" "math/rand" "strings" @@ -57,6 +58,11 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin if len(implementation.StubIdentifier) > 0 { stubIdentifier = "_" + strings.ToLower(implementation.StubIdentifier) } + + if (stubIdentifier == "") { + return errors.New ("pascal Stub Identifier must not be empty"); + } + IntfWrapperTypesName := path.Join(outputFolder, baseName+"_types.pas"); log.Printf("Creating \"%s\"", IntfWrapperTypesName) @@ -67,11 +73,9 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin typesWrapperfile.WritePascalLicenseHeader(component, fmt.Sprintf("This is an autogenerated Pascal type definition file in order to allow easy\ndevelopment of %s. The functions in this file need to be implemented. It needs to be generated only once.", libraryname), true) - - buildPascalTypeDefinition (component, typesWrapperfile, namespace, baseName); - + IntfWrapperExceptionName := path.Join(outputFolder, baseName+"_exception.pas"); log.Printf("Creating \"%s\"", IntfWrapperExceptionName) exceptionWrapperfile, err := CreateLanguageFile(IntfWrapperExceptionName, indentString) @@ -81,8 +85,6 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin exceptionWrapperfile.WritePascalLicenseHeader(component, fmt.Sprintf("This is an autogenerated Pascal exception class definition file in order to allow easy\ndevelopment of %s. The functions in this file need to be implemented. It needs to be generated only once.", libraryname), true) - - buildPascalExceptionDefinition (component, exceptionWrapperfile, namespace, baseName); @@ -95,11 +97,9 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin interfaceWrapperfile.WritePascalLicenseHeader(component, fmt.Sprintf("This is an autogenerated Pascal interface definition file in order to allow easy\ndevelopment of %s. The functions in this file need to be implemented. It needs to be generated only once.", libraryname), true) - - buildPascalInterfaceDefinition (component, interfaceWrapperfile, namespace, baseName); - - + + IntfWrapperExportName := path.Join(outputFolder, baseName+"_exports.pas"); log.Printf("Creating \"%s\"", IntfWrapperExportName) exportWrapperfile, err := CreateLanguageFile(IntfWrapperExportName, indentString) @@ -110,17 +110,26 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin fmt.Sprintf("This is an autogenerated Pascal export implementation file in order to allow easy\ndevelopment of %s. The functions in this file need to be implemented. It needs to be generated only once.", libraryname), true) - buildPascalExportsDefinition (component, exportWrapperfile, namespace, baseName); - + buildPascalExportsDefinition (component, exportWrapperfile, namespace, baseName, stubIdentifier, implementation.ClassIdentifier); + IntfWrapperStubName := path.Join(stubOutputFolder, baseName + stubIdentifier + ".pas") - log.Printf("Creating \"%s\"", IntfWrapperStubName) - templatefile, err := CreateLanguageFile (IntfWrapperStubName, indentString) - if err != nil { - return err + if forceRecreation || (!FileExists(IntfWrapperStubName) ) { + log.Printf("Creating \"%s\"", IntfWrapperStubName) + templatefile, err := CreateLanguageFile (IntfWrapperStubName, indentString) + if err != nil { + return err + } + templatefile.WritePascalLicenseHeader(component, + fmt.Sprintf("This is an autogenerated Pascal implementation file in order to allow easy\ndevelopment of %s. It needs to be generated only once.", libraryname), + true) + + err = buildStubImplementation (component, templatefile, namespace, baseName, stubIdentifier); + if err != nil { + return err + } + } else { + log.Printf("Omitting recreation of Stub implementation \"%s\"", IntfWrapperStubName) } - templatefile.WritePascalLicenseHeader(component, - fmt.Sprintf("This is an autogenerated Pascal implementation file in order to allow easy\ndevelopment of %s. It needs to be generated only once.", libraryname), - true) IntfWrapperLPIName := path.Join(projectOutputFolder, baseName+".lpi"); @@ -129,7 +138,6 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin if err != nil { return err } - err = buildLPIImplementation (component, lpifile, namespace, baseName); if err != nil { return err @@ -145,21 +153,46 @@ func BuildImplementationPascal(component ComponentDefinition, outputFolder strin lprfile.WritePascalLicenseHeader(component, fmt.Sprintf("This is an autogenerated Pascal project file in order to allow easy\ndevelopment of %s.", libraryname), true); - err = buildLPRImplementation (component, lprfile, namespace, baseName); if err != nil { return err } - + + defFileName := path.Join(projectOutputFolder, baseName+".def"); + log.Printf("Creating \"%s\"", defFileName) + defFile, err := CreateLanguageFile (defFileName, "") + if err != nil { + return err + } + err = buildDefFile(component, defFile, namespace) + if err != nil { + return err + } + err = buildPascalStub(component, namespace, implementation.ClassIdentifier, baseName, stubOutputFolder, indentString, stubIdentifier, forceRecreation) if err != nil { return err } - return nil } +// buildDefFile writes a module definition file with all exported functions +func buildDefFile(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string) error { + w.Writeln("EXPORTS") + global := componentdefinition.Global; + for _, method := range global.Methods { + w.Writeln("%s_%s", strings.ToLower(NameSpace), strings.ToLower(method.MethodName)) + } + for _, class := range componentdefinition.Classes { + for _, method := range class.Methods { + w.Writeln("%s_%s_%s", strings.ToLower(NameSpace), strings.ToLower(class.ClassName), strings.ToLower(method.MethodName)) + } + } + return nil +} + + func buildPascalTypeDefinition(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { w.Writeln ("{$MODE DELPHI}"); @@ -173,11 +206,14 @@ func buildPascalTypeDefinition(componentdefinition ComponentDefinition, w Langua w.Writeln (" sysutils;"); w.Writeln (""); - writePascalBaseTypeDefinitions (componentdefinition, w, NameSpace, BaseName); + err := writePascalBaseTypeDefinitions (componentdefinition, w, NameSpace, BaseName); + if (err != nil) { + return err; + } w.Writeln ("implementation"); w.Writeln (""); - + w.Writeln ("end."); return nil; @@ -281,7 +317,9 @@ func buildPascalInterfaceDefinition(componentdefinition ComponentDefinition, w L w.Writeln (" Classes,"); w.Writeln (" sysutils;"); w.Writeln (""); - + + writeEnumConversionInterface (componentdefinition, w, NameSpace); + w.Writeln ("") w.Writeln ("(*************************************************************************************************************************") w.Writeln (" Interface definition for BaseClass") @@ -295,8 +333,8 @@ func buildPascalInterfaceDefinition(componentdefinition ComponentDefinition, w L return err } w.Writeln (" ['{%s}']", uuid); - - w.Writeln (" end;"); + + w.Writeln (" end;"); w.Writeln ("") @@ -325,7 +363,9 @@ func buildPascalInterfaceDefinition(componentdefinition ComponentDefinition, w L for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - err := writePascalClassMethodDefinition(method, w, NameSpace, class.ClassName, false, " ", true) + w.AddIndentationLevel(2) + err := writePascalImplClassMethodDefinition(method, w, NameSpace, class.ClassName, false) + w.AddIndentationLevel(-2) if err != nil { return err; } @@ -339,6 +379,8 @@ func buildPascalInterfaceDefinition(componentdefinition ComponentDefinition, w L w.Writeln ("implementation"); w.Writeln (""); + writeEnumConversionImplementation (componentdefinition, w, NameSpace); + w.Writeln ("end."); return nil; @@ -346,9 +388,9 @@ func buildPascalInterfaceDefinition(componentdefinition ComponentDefinition, w L } -func writePascalExportDefinition (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool, spacing string, doComment bool) (error) { +func writePascalExportDefinition (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool, doComment bool) (error) { - PascalExportName := GetCExportName (NameSpace, ClassName, method, isGlobal); + PascalExportName := GetCExportName (NameSpace, ClassName, method, isGlobal); parameters := ""; if (isGlobal) { @@ -357,11 +399,11 @@ func writePascalExportDefinition (method ComponentDefinitionMethod, w LanguageWr } if (doComment) { - w.Writeln ( spacing + "(**"); - w.Writeln ( spacing + "* %s", method.MethodDescription); - w.Writeln ( spacing + "*"); + w.Writeln("(**"); + w.Writeln("* %s", method.MethodDescription); + w.Writeln("*"); if (!isGlobal) { - w.Writeln ( spacing + "* @param[in] p%s - %s instance.", ClassName, ClassName); + w.Writeln("* @param[in] p%s - %s instance.", ClassName, ClassName); } } @@ -375,11 +417,9 @@ func writePascalExportDefinition (method ComponentDefinitionMethod, w LanguageWr } for _, pascalParam := range pascalParams { - if (doComment) { - w.Writeln (spacing + pascalParam.ParamComment); + w.Writeln(pascalParam.ParamComment); } - if (parameters != "") { parameters = parameters + "; "; } @@ -389,17 +429,228 @@ func writePascalExportDefinition (method ComponentDefinitionMethod, w LanguageWr } if (doComment) { - w.Writeln (spacing + "* @return error code or 0 (success)"); - w.Writeln (spacing + "*)"); + w.Writeln("* @return error code or 0 (success)"); + w.Writeln("*)"); } - w.Writeln (spacing + "function %s (%s): T%sResult; cdecl;", PascalExportName, parameters, NameSpace); + w.Writeln ("function %s (%s): T%sResult; cdecl;", PascalExportName, parameters, NameSpace); return nil; } -func writePascalClassExportImplementation (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, spacing string, isGlobal bool) (error) { +func generatePrePostCallPascalFunctionCode(method ComponentDefinitionMethod, NameSpace string, ClassIdentifier string, ClassName string) ([]string, []string, []string, []string, string, string, error) { + variableDefinitions := make([]string, 0); + preCallCode := make([]string, 0); + postCallCode := make([]string, 0); + checkInputCode := make([]string, 0); + callParameters := ""; + resultVariable := ""; + + for k := 0; k < len(method.Params); k++ { + param := method.Params[k] + + pascalParams, err := generatePlainPascalParameter(param, ClassName, method.MethodName, NameSpace); + if (err != nil) { + return make([]string, 0), make([]string, 0), make([]string, 0), make([]string, 0), "", "", err; + } + + switch param.ParamPass { + case "in": + if callParameters != "" { + callParameters = callParameters + ", " + } + switch param.ParamType { + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "single", "double": + callParameters = callParameters + pascalParams[0].ParamName + case "bool": + callParameters = callParameters + pascalParams[0].ParamName + " <> 0" + case "enum": + callParameters = callParameters + "convertConstTo" + param.ParamClass + " (" + pascalParams[0].ParamName + ")" + case "struct": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + callParameters = callParameters + pascalParams[0].ParamName + "^"; + + case "basicarray", "structarray": + checkInputCode = append (checkInputCode, fmt.Sprintf("if ((not Assigned (%s)) and (%s>0)) then", pascalParams[1].ParamName, pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + callParameters = callParameters + fmt.Sprintf("%s, %s", pascalParams[0].ParamName, pascalParams[1].ParamName) + + case "handle": + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Object%s: TObject;", param.ParamName)); + checkInputCode = append (checkInputCode, fmt.Sprintf("Object%s := TObject (%s);", param.ParamName, pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf("if (not Supports (Object%s, I%s%s)) then", param.ParamName, NameSpace, param.ParamClass)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDCAST);", NameSpace, strings.ToUpper(NameSpace))) + checkInputCode = append (checkInputCode, ""); + + callParameters = callParameters + fmt.Sprintf("Object%s", param.ParamName) + + case "string": + checkInputCode = append (checkInputCode, fmt.Sprintf("if (not Assigned (%s)) then", pascalParams[0].ParamName)); + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))); + + callParameters = callParameters + "StrPas (" + pascalParams[0].ParamName + ")"; + + case "functiontype": + callParameters = callParameters + pascalParams[0].ParamName + + default: + return make([]string, 0), make([]string, 0), make([]string, 0), make([]string, 0), "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) + } + + case "out": + if callParameters != "" { + callParameters = callParameters + ", " + } + + switch param.ParamType { + + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "single", "double", "struct": + checkInputCode = append (checkInputCode, fmt.Sprintf("if (not Assigned (%s)) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);\n", NameSpace, strings.ToUpper(NameSpace))) + + callParameters = callParameters + pascalParams[0].ParamName + "^"; + + case "enum": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: T%s%s;", param.ParamName, NameSpace, param.ParamClass)); + + callParameters = callParameters + fmt.Sprintf ("Result%s", param.ParamName); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := convert%sToConst (Result%s);", pascalParams[0].ParamName, param.ParamClass, param.ParamName)) + + case "bool": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: Boolean;", param.ParamName)); + + callParameters = callParameters + fmt.Sprintf ("Result%s", param.ParamName); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := Ord (Result%s);", pascalParams[0].ParamName, param.ParamName)) + + case "basicarray", "structarray": + checkInputCode = append (checkInputCode, fmt.Sprintf("if ((not Assigned (%s)) and (not Assigned(%s))) then", pascalParams[1].ParamName, pascalParams[2].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + callParameters = callParameters + fmt.Sprintf("%s, %s, %s", pascalParams[0].ParamName, pascalParams[1].ParamName, pascalParams[2].ParamName) + + case "string": + checkInputCode = append (checkInputCode, fmt.Sprintf("if ((not Assigned (%s)) and (not Assigned(%s))) then", pascalParams[2].ParamName, pascalParams[1].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: String;", param.ParamName)); + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Len%s: Cardinal;", param.ParamName)); + + callParameters = callParameters + "Result" + param.ParamName; + + postCallCode = append (postCallCode, fmt.Sprintf("Len%s := Length (Result%s);", param.ParamName, param.ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf("if Assigned(%s) then", pascalParams[1].ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf(" %s^ := Len%s;", pascalParams[1].ParamName, param.ParamName)); + + postCallCode = append (postCallCode, fmt.Sprintf("if Assigned(%s) then begin", pascalParams[2].ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf(" if (Len%s >= %s) then", param.ParamName, pascalParams[0].ParamName)); + postCallCode = append (postCallCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_BUFFERTOOSMALL);", NameSpace, strings.ToUpper(NameSpace))) + postCallCode = append (postCallCode, fmt.Sprintf(" Move (PAnsiChar (Result%s)^, %s^, Len%s + 1);", param.ParamName, pascalParams[2].ParamName, param.ParamName)); + postCallCode = append (postCallCode, fmt.Sprintf("end;")); + + default: + return make([]string, 0), make([]string, 0), make([]string, 0), make([]string, 0), "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) + } + + case "return": + + switch param.ParamType { + + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "single", "double": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: %s;", param.ParamName, pascalParams[0].ParamType)); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := Result%s;", pascalParams[0].ParamName, param.ParamName)) + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + case "bool": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: Boolean;", param.ParamName)); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := Ord (Result%s);", pascalParams[0].ParamName, param.ParamName)) + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + case "enum": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: T%s%s;", param.ParamName, NameSpace, param.ParamClass)); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := convert%sToConst (Result%s);", pascalParams[0].ParamName, param.ParamClass, param.ParamName)) + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + case "struct": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned (%s) then", pascalParams[0].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: %s;", param.ParamName, pascalParams[0].ParamType)); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := Result%s;", pascalParams[0].ParamName, param.ParamName)) + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + case "string": + checkInputCode = append (checkInputCode, fmt.Sprintf("if ((not Assigned (%s)) and (not Assigned(%s))) then", pascalParams[2].ParamName, pascalParams[1].ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: String;", param.ParamName)); + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Len%s: Cardinal;", param.ParamName)); + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + postCallCode = append (postCallCode, fmt.Sprintf("Len%s := Length (Result%s);", param.ParamName, param.ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf("if Assigned(%s) then", pascalParams[1].ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf(" %s^ := Len%s;", pascalParams[1].ParamName, param.ParamName)); + + postCallCode = append (postCallCode, fmt.Sprintf("if Assigned(%s) then begin", pascalParams[2].ParamName)) + postCallCode = append (postCallCode, fmt.Sprintf(" if (Len%s >= %s) then", param.ParamName, pascalParams[0].ParamName)); + postCallCode = append (postCallCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_BUFFERTOOSMALL);", NameSpace, strings.ToUpper(NameSpace))) + postCallCode = append (postCallCode, fmt.Sprintf(" Move (PAnsiChar (Result%s)^, %s^, Len%s + 1);", param.ParamName, pascalParams[2].ParamName, param.ParamName)); + postCallCode = append (postCallCode, fmt.Sprintf("end;")); + + case "handle": + checkInputCode = append (checkInputCode, fmt.Sprintf("if not Assigned(p%s) then", param.ParamName)) + checkInputCode = append (checkInputCode, fmt.Sprintf(" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper(NameSpace))) + + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Result%s: TObject;", param.ParamName)); + + resultVariable = fmt.Sprintf("Result%s", param.ParamName); + + postCallCode = append (postCallCode, fmt.Sprintf("%s^ := Result%s;", pascalParams[0].ParamName, param.ParamName)) + + default: + return make([]string, 0), make([]string, 0), make([]string, 0), make([]string, 0), "", "", fmt.Errorf("method parameter type \"%s\" of param pass \"%s\" is not implemented for %s::%s(%s) )", param.ParamType, param.ParamPass, ClassName, method.MethodName, param.ParamName) + } + + default: + return make([]string, 0), make([]string, 0), make([]string, 0), make([]string, 0), "", "", fmt.Errorf("invalid method parameter passing \"%s\" for %s.%s (%s)", param.ParamPass, ClassName, method.MethodName, param.ParamName) + } + } + + return variableDefinitions, checkInputCode, preCallCode, postCallCode, callParameters, resultVariable, nil +} + + + +func writePascalClassExportImplementation (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool, ClassIdentifier string) (error) { /*var ANumberObject: TObject; @@ -433,60 +684,82 @@ begin end; */ - variableDefinitions := make([]string, 0); - parameterChecks := make([]string, 0); - + variableDefinitions, parameterChecks, preCallCode, postCallCode, callParameters, resultVariable, err := generatePrePostCallPascalFunctionCode (method, NameSpace, ClassIdentifier, ClassName) + if (err != nil) { + return err; + } + if (!isGlobal) { // Define variables - variableDefinitions = append (variableDefinitions, fmt.Sprintf (" A%sObject: TObject;", ClassName)); - variableDefinitions = append (variableDefinitions, fmt.Sprintf (" A%sInterface: I%s%s;", ClassName, NameSpace, ClassName)); + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Object%s: TObject;", ClassName)); + variableDefinitions = append (variableDefinitions, fmt.Sprintf (" Intf%s: I%s%s;", ClassName, NameSpace, ClassName)); - parameterChecks = append (parameterChecks, fmt.Sprintf (" if not Assigned (p%s) then", ClassName)); - parameterChecks = append (parameterChecks, fmt.Sprintf (" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper (NameSpace))); + parameterChecks = append (parameterChecks, fmt.Sprintf ("if not Assigned (p%s) then", ClassName)); + parameterChecks = append (parameterChecks, fmt.Sprintf (" raise E%sException.Create (%s_ERROR_INVALIDPARAM);", NameSpace, strings.ToUpper (NameSpace))); } if (len (variableDefinitions) > 0) { - w.Writeln (spacing + "var"); - w.Writelns (spacing, variableDefinitions); - } - w.Writeln (spacing + "begin"); - w.Writeln (spacing + " try"); - w.Writelns (spacing, parameterChecks); - - w.Writeln (spacing + ""); + w.Writeln("var"); + w.Writelns("", variableDefinitions); + } + w.Writeln("begin"); + w.Writeln(" try"); + w.Writelns (" ", parameterChecks); + + w.Writeln (""); if (!isGlobal) { - w.Writeln (spacing + " A%sObject := TObject (p%s);", ClassName, ClassName); - w.Writeln (spacing + " if Supports (A%sObject, I%s%s) then begin", ClassName, NameSpace, ClassName); - w.Writeln (spacing + " A%sInterface := A%sObject as I%s%s;", ClassName, ClassName, NameSpace, ClassName); + w.Writeln (" Object%s := TObject (p%s);", ClassName, ClassName); + w.Writeln (" if Supports (Object%s, I%s%s) then begin", ClassName, NameSpace, ClassName); + w.Writeln (" Intf%s := Object%s as I%s%s;", ClassName, ClassName, NameSpace, ClassName); + } + + w.Writelns("", preCallCode); + + resultVariableAssignment := ""; + if (resultVariable != "") { + resultVariableAssignment = resultVariable + " := "; + } + + classInstanceSpacing := " "; + classInstanceToCall := "Intf" + ClassName; + postCallCodeSpacing := " "; + if (isGlobal) { + classInstanceToCall = "T" + NameSpace + "Wrapper"; + classInstanceSpacing = " "; + postCallCodeSpacing = " "; } + w.Writeln(classInstanceSpacing + "%s%s.%s(%s);", resultVariableAssignment, classInstanceToCall, method.MethodName, callParameters); + w.Writeln(""); + + w.Writelns (postCallCodeSpacing, postCallCode); if (!isGlobal) { - w.Writeln (spacing + " end else"); - w.Writeln (spacing + " raise E%sException.Create (%s_ERROR_INVALIDCAST);", NameSpace, strings.ToUpper (NameSpace)); - } - - w.Writeln (spacing + ""); - w.Writeln (spacing + " Result := %s_SUCCESS;", strings.ToUpper (NameSpace)); - w.Writeln (spacing + " except"); - w.Writeln (spacing + " On E: E%sException do begin", NameSpace); - w.Writeln (spacing + " Result := E.ErrorCode;"); - w.Writeln (spacing + " end;"); - w.Writeln (spacing + " On E: Exception do begin"); - w.Writeln (spacing + " Result := %s_ERROR_GENERICEXCEPTION;", strings.ToUpper (NameSpace)); - w.Writeln (spacing + " end;"); - w.Writeln (spacing + " end;"); - w.Writeln (spacing + "end;"); - w.Writeln (spacing + ""); + w.Writeln (" end else"); + w.Writeln (" raise E%sException.Create (%s_ERROR_INVALIDCAST);", NameSpace, strings.ToUpper (NameSpace)); + w.Writeln (""); + } + + w.Writeln (" Result := %s_SUCCESS;", strings.ToUpper (NameSpace)); + w.Writeln (" except"); + w.Writeln (" On E: E%sException do begin", NameSpace); + w.Writeln (" Result := E.ErrorCode;"); + w.Writeln (" end;"); + w.Writeln (" On E: Exception do begin"); + w.Writeln (" Result := %s_ERROR_GENERICEXCEPTION;", strings.ToUpper (NameSpace)); + w.Writeln (" end;"); + w.Writeln (" end;"); + w.Writeln ("end;"); + w.Writeln (""); return nil; } -func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { +func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string, stubIdentifier string, ClassIdentifier string) error { global := componentdefinition.Global; @@ -496,6 +769,7 @@ func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w Lan w.Writeln ("interface"); w.Writeln (""); w.Writeln ("uses"); + w.Writeln (" %s%s,", BaseName, stubIdentifier); w.Writeln (" %s_types,", BaseName); w.Writeln (" %s_interfaces,", BaseName); w.Writeln (" %s_exception,", BaseName); @@ -512,10 +786,9 @@ func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w Lan w.Writeln("") for j := 0; j < len(class.Methods); j++ { - method := class.Methods[j] - err := writePascalExportDefinition (method, w, NameSpace, class.ClassName, false, "", true); + err := writePascalExportDefinition (method, w, NameSpace, class.ClassName, false, true); if (err != nil) { return err; } @@ -530,11 +803,10 @@ func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w Lan w.Writeln("**************************************************************************************************************************)") w.Writeln (""); - for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - err := writePascalExportDefinition (method, w, NameSpace, "Wrapper", true, "", true); + err := writePascalExportDefinition (method, w, NameSpace, "Wrapper", true, true); if (err != nil) { return err; } @@ -553,12 +825,12 @@ func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w Lan method := class.Methods[j] - err := writePascalExportDefinition (method, w, NameSpace, class.ClassName, false, "", false); + err := writePascalExportDefinition (method, w, NameSpace, class.ClassName, false, false); if (err != nil) { return err; } - err = writePascalClassExportImplementation(method, w, NameSpace, class.ClassName, "", false); + err = writePascalClassExportImplementation(method, w, NameSpace, class.ClassName, false, ClassIdentifier); if (err != nil) { return err; } @@ -570,12 +842,12 @@ func buildPascalExportsDefinition(componentdefinition ComponentDefinition, w Lan for j := 0; j < len(global.Methods); j++ { method := global.Methods[j] - err := writePascalExportDefinition (method, w, NameSpace, "Wrapper", true, "", false); + err := writePascalExportDefinition (method, w, NameSpace, "Wrapper", true, false); if (err != nil) { return err; } - err = writePascalClassExportImplementation(method, w, NameSpace, "Wrapper", "", true); + err = writePascalClassExportImplementation(method, w, NameSpace, "Wrapper", true, ClassIdentifier); if (err != nil) { return err; } @@ -682,6 +954,7 @@ func buildLPIImplementation(componentdefinition ComponentDefinition, w LanguageW w.Writeln (" </Target>"); w.Writeln (" <SearchPaths>"); w.Writeln (" <IncludeFiles Value=\"$(ProjOutDir)\"/>"); + w.Writeln (" <OtherUnitFiles Value=\"Stub;Interfaces\"/>"); w.Writeln (" <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>"); w.Writeln (" </SearchPaths>"); w.Writeln (" <Parsing>"); @@ -711,11 +984,15 @@ func buildLPIImplementation(componentdefinition ComponentDefinition, w LanguageW w.Writeln (" <FormatVersion Value=\"1\"/>"); w.Writeln (" </local>"); w.Writeln (" </RunParams>"); - w.Writeln (" <Units Count=\"%d\">", 1); + w.Writeln (" <Units Count=\"%d\">", 2); w.Writeln (" <Unit0>"); w.Writeln (" <Filename Value=\"Interfaces\\%s.lpr\"/>", BaseName); w.Writeln (" <IsPartOfProject Value=\"True\"/>"); w.Writeln (" </Unit0>"); + w.Writeln (" <Unit1>"); + w.Writeln (" <Filename Value=\"Stub\\%s.pas\"/>", BaseName); + w.Writeln (" <IsPartOfProject Value=\"True\"/>"); + w.Writeln (" </Unit1>"); w.Writeln (" </Units>"); w.Writeln (" </ProjectOptions>"); w.Writeln (" <CompilerOptions>"); @@ -725,7 +1002,8 @@ func buildLPIImplementation(componentdefinition ComponentDefinition, w LanguageW w.Writeln (" <Filename Value=\"bin\\$(TargetCPU)-$(TargetOS)\\Release\\%s\"/>", BaseName); w.Writeln (" </Target>"); w.Writeln (" <SearchPaths>"); - w.Writeln (" <IncludeFiles Value=\"$(ProjOutDir)\"/>"); + w.Writeln (" <IncludeFiles Value=\"$(ProjOutDir)\"/>"); + w.Writeln (" <OtherUnitFiles Value=\"Stub;Interfaces\"/>"); w.Writeln (" <UnitOutputDirectory Value=\"lib\\$(TargetCPU)-$(TargetOS)\"/>"); w.Writeln (" </SearchPaths>"); w.Writeln (" <Parsing>"); @@ -767,24 +1045,90 @@ func buildLPIImplementation(componentdefinition ComponentDefinition, w LanguageW } -func writePascalClassMethodDummyStub (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, outClassName string, isGlobal bool, spacing string) (error) { +func getPascalImplClassParameters(method ComponentDefinitionMethod, NameSpace string, ClassName string, isGlobal bool, isImplementation bool) (string, string, error) { + parameters := ""; + returnType := ""; + + for k := 0; k < len(method.Params); k++ { + param := method.Params [k]; + ParamTypeName, err := getPascalParameterType(param.ParamType, NameSpace, param.ParamClass, false, isImplementation); + if err != nil { + return "", "", err; + } + + switch (param.ParamPass) { + case "in": + switch (param.ParamType) { + case "basicarray", "structarray": + if (parameters != "") { + parameters = parameters + "; "; + } + parameters = parameters + "const A" + param.ParamName + "Count: Cardinal" + parameters = parameters + "; const A" + param.ParamName + ": " + ParamTypeName + case "handle": + if (parameters != "") { + parameters = parameters + "; "; + } + parameters = parameters + "A" + param.ParamName + ": " + ParamTypeName; + default: + if (parameters != "") { + parameters = parameters + "; "; + } + parameters = parameters + "const A" + param.ParamName + ": " + ParamTypeName; + } + + + case "out": + switch (param.ParamType) { + case "basicarray", "structarray": + if (parameters != "") { + parameters = parameters + "; "; + } + parameters = parameters + "const A" + param.ParamName + "Count: Cardinal" + parameters = parameters + "; P" + param.ParamName + "NeededCount: PCardinal" + parameters = parameters + "; A" + param.ParamName + ": " + ParamTypeName + default: + if (parameters != "") { + parameters = parameters + "; "; + } + parameters = parameters + "out A" + param.ParamName + ": " + ParamTypeName; + } + + case "return": + if param.ParamType == "basicarray" || param.ParamType == "structarray" { + return "", "", fmt.Errorf ("return value \"%s\" is not supported for Pascal method \"%s\"", param.ParamName, method.MethodName); + } + if (returnType != "") { + return "", "", fmt.Errorf ("duplicate return value \"%s\" for Pascal method \"%s\"", param.ParamName, method.MethodName); + } + returnType = ParamTypeName; + } + } - parameters, returnType, err := getPascalClassParameters (method, NameSpace, ClassName, isGlobal, true); + return parameters, returnType, nil; +} + +func writePascalClassMethodDummyStub (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, outClassName string, isGlobal bool) (error) { + parameters, returnType, err := getPascalImplClassParameters (method, NameSpace, ClassName, isGlobal, true); if (err != nil) { return err; } + + classPrefix := ""; + if (isGlobal) { + classPrefix = "class "; + } if (returnType == "") { - w.Writeln ( spacing + "procedure %s.%s(%s);", outClassName, method.MethodName, parameters); + w.Writeln("%sprocedure %s.%s(%s);", classPrefix, outClassName, method.MethodName, parameters); } else { - w.Writeln ( spacing + "function %s.%s(%s): %s;", outClassName, method.MethodName, parameters, returnType); + w.Writeln("%sfunction %s.%s(%s): %s;", classPrefix, outClassName, method.MethodName, parameters, returnType); } - w.Writeln ( spacing + "begin"); - w.Writeln ( spacing + " raise E%sException (%s_ERROR_NOTIMPLEMENTED)", NameSpace, strings.ToUpper (NameSpace)); - w.Writeln ( spacing + "end;"); - w.Writeln ( spacing + ""); - + w.Writeln("begin"); + w.Writeln(" raise E%sException (%s_ERROR_NOTIMPLEMENTED);", NameSpace, strings.ToUpper (NameSpace)); + w.Writeln("end;"); + w.Writeln(""); return nil; } @@ -794,16 +1138,53 @@ func writePascalClassMethodDummyStub (method ComponentDefinitionMethod, w Langua func buildPascalStub(component ComponentDefinition, NameSpace string, ClassIdentifier string, BaseName string, outputFolder string, indentString string, stubIdentifier string, forceRecreation bool) error { - for i := 0; i < len(component.Classes); i++ { - class := component.Classes[i] - - parentClassName := class.ParentClass - if parentClassName == "" { - parentClassName = "BaseClass" + baseClassName := "T" + ClassIdentifier + NameSpace + "BaseClass" + StubFileName := path.Join(outputFolder, BaseName + stubIdentifier + "_" +"baseclass.pas"); + if forceRecreation || !FileExists(StubFileName) { + log.Printf("Creating \"%s\"", StubFileName) + w, err := CreateLanguageFile(StubFileName, indentString) + if err != nil { + return err } + w.WritePascalLicenseHeader(component, + fmt.Sprintf("This is the class declaration of %s", baseClassName), + false) + w.Writeln ("{$MODE DELPHI}"); + w.Writeln ("unit %s%s_%s;", BaseName, stubIdentifier, strings.ToLower("BaseClass")); + w.Writeln (""); + w.Writeln ("interface"); + w.Writeln (""); + w.Writeln ("uses"); + w.Writeln (" %s_interfaces,", BaseName); + w.Writeln (" Classes,"); + w.Writeln (" sysutils;"); + w.Writeln (""); + + w.Writeln ("type"); + w.Writeln (" %s = class (TObject, I%sBaseClass)", baseClassName, NameSpace); + w.Writeln (" end;"); + w.Writeln ("") + + w.Writeln ("implementation"); + w.Writeln (""); + w.Writeln ("end."); + } else { + log.Printf("Omitting recreation of Stub implementation for \"%s\"", baseClassName) + } + + + for i := 0; i < len(component.Classes); i++ { + class := component.Classes[i] outClassName := "T" + ClassIdentifier + NameSpace + class.ClassName - outparentClassName := "T" + ClassIdentifier + NameSpace + parentClassName + + outparentClassName := ""; + + if class.ParentClass != "" { + outparentClassName = "T" + ClassIdentifier + NameSpace + class.ParentClass; + } else { + outparentClassName = baseClassName; + } StubFileName := path.Join(outputFolder, BaseName + stubIdentifier + "_" +strings.ToLower(class.ClassName)+".pas"); if !forceRecreation && ( FileExists(StubFileName) ) { @@ -819,7 +1200,6 @@ func buildPascalStub(component ComponentDefinition, NameSpace string, ClassIdent w.WritePascalLicenseHeader(component, fmt.Sprintf("This is the class declaration of %s", outClassName), false) - w.Writeln ("{$MODE DELPHI}"); w.Writeln ("unit %s%s_%s;", BaseName, stubIdentifier, strings.ToLower(class.ClassName)); @@ -832,13 +1212,15 @@ func buildPascalStub(component ComponentDefinition, NameSpace string, ClassIdent w.Writeln (" %s_exception,", BaseName); if (class.ParentClass != "") { - w.Writeln (" %s%s_%s,", BaseName, stubIdentifier, strings.ToLower(class.ClassName)); + w.Writeln (" %s%s_%s,", BaseName, stubIdentifier, strings.ToLower(class.ParentClass)); + } else { + w.Writeln (" %s%s_%s,", BaseName, stubIdentifier, strings.ToLower("BaseClass")); } w.Writeln (" Classes,"); w.Writeln (" sysutils;"); w.Writeln (""); - + w.Writeln ("type"); w.Writeln (" %s = class (%s, I%s%s)", outClassName, outparentClassName, NameSpace, class.ClassName); @@ -850,7 +1232,9 @@ func buildPascalStub(component ComponentDefinition, NameSpace string, ClassIdent for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - err := writePascalClassMethodDefinition(method, w, NameSpace, class.ClassName, false, " ", true) + w.AddIndentationLevel(3) + err := writePascalImplClassMethodDefinition(method, w, NameSpace, class.ClassName, false) + w.AddIndentationLevel(-3) if err != nil { return err; } @@ -859,25 +1243,94 @@ func buildPascalStub(component ComponentDefinition, NameSpace string, ClassIdent w.Writeln (" end;"); w.Writeln ("") - + w.Writeln ("implementation"); w.Writeln (""); - for j := 0; j < len(class.Methods); j++ { method := class.Methods[j] - err := writePascalClassMethodDummyStub(method, w, NameSpace, class.ClassName, outClassName, false, " ") + err := writePascalClassMethodDummyStub(method, w, NameSpace, class.ClassName, outClassName, false); if err != nil { return err; } } - w.Writeln ("end."); - } return nil } +func writePascalImplClassMethodDefinition (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool) (error) { + + parameters, returnType, err := getPascalImplClassParameters (method, NameSpace, ClassName, isGlobal, true); + if (err != nil) { + return err; + } + + classPrefix := ""; + if (isGlobal) { + classPrefix = "class "; + } + + if (returnType == "") { + w.Writeln("%sprocedure %s(%s);", classPrefix, method.MethodName, parameters); + } else { + w.Writeln("%sfunction %s(%s): %s;", classPrefix, method.MethodName, parameters, returnType); + } + + return nil; +} + + +func buildStubImplementation(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string, stubIdentifier string) error { + + global := componentdefinition.Global; + + w.Writeln ("{$MODE DELPHI}"); + w.Writeln ("Unit %s%s;", BaseName, stubIdentifier); + w.Writeln (""); + w.Writeln ("interface"); + w.Writeln (""); + w.Writeln ("uses"); + w.Writeln (" %s_types,", BaseName); + w.Writeln (" %s_exception,", BaseName); + w.Writeln (" Classes,"); + w.Writeln (" sysutils;"); + w.Writeln (""); + w.Writeln ("type"); + w.Writeln (" T%sWrapper = class (TObject)", NameSpace); + w.Writeln (" public"); + + for j := 0; j < len(global.Methods); j++ { + method := global.Methods[j] + w.AddIndentationLevel(3) + err := writePascalImplClassMethodDefinition(method, w, NameSpace, "Wrapper", true) + w.AddIndentationLevel(-3) + if err != nil { + return err; + } + } + + w.Writeln (" end;"); + w.Writeln (""); + w.Writeln (""); + w.Writeln ("implementation"); + w.Writeln (""); + + for j := 0; j < len(global.Methods); j++ { + method := global.Methods[j] + err := writePascalClassMethodDummyStub(method, w, NameSpace, "Wrapper", "T" + NameSpace + "Wrapper", true) + if err != nil { + return err; + } + } + w.Writeln (""); + + + w.Writeln ("end."); + + return nil; +} + diff --git a/Source/componentdefinition.go b/Source/componentdefinition.go index b75f8c5c..6a518c93 100644 --- a/Source/componentdefinition.go +++ b/Source/componentdefinition.go @@ -183,6 +183,7 @@ type ComponentDefinitionLicense struct { // ComponentDefinition the complete definition of the component's API type ComponentDefinition struct { + ACTVersion string XMLName xml.Name `xml:"component"` Version string `xml:"version,attr"` Copyright string `xml:"copyright,attr"` @@ -207,8 +208,8 @@ func getIndentationString (str string) string { } index := strings.Index(str, "spaces"); if (index < 1) { - log.Printf ("invalid indentation: \"%s\". Using \"4spaces\" instead\n", str); - return " "; + log.Printf ("invalid indentation: \"%s\". Using \"tabs\" instead\n", str); + return "\t"; } numSpaces, err := strconv.ParseUint(str[0:index], 10, 64); if err!=nil { diff --git a/Source/languagec.go b/Source/languagec.go new file mode 100644 index 00000000..ac47818d --- /dev/null +++ b/Source/languagec.go @@ -0,0 +1,645 @@ +/*++ + +Copyright (C) 2018 Autodesk Inc. (Original Author) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--*/ + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// languagec.go +// functions to generate the C-layer of a library's API (can be used in bindings or implementation) +////////////////////////////////////////////////////////////////////////////////////////////////////// + +package main + +import ( + "fmt" + "path" + "strings" + "log" +) + +// BuildBindingC builds C-bindings of a library's API in form of automatically C functions +func BuildBindingC(component ComponentDefinition, outputFolderBindingC string) error { + CTypesHeaderName := path.Join(outputFolderBindingC, component.BaseName + "_types.h"); + log.Printf("Creating \"%s\"", CTypesHeaderName) + err := CreateCTypesHeader (component, CTypesHeaderName); + if (err != nil) { + return err; + } + + CHeaderName := path.Join(outputFolderBindingC, component.BaseName + ".h"); + log.Printf("Creating \"%s\"", CTypesHeaderName) + err = CreateCHeader (component, CHeaderName); + if (err != nil) { + return err; + } + + return nil; +} + +// CreateCTypesHeader creates a C header file for the types in component's API +func CreateCTypesHeader (component ComponentDefinition, CTypesHeaderName string) (error) { + hTypesFile, err := CreateLanguageFile(CTypesHeaderName, " "); + if (err != nil) { + return err; + } + hTypesFile.WriteCLicenseHeader (component, + fmt.Sprintf ("This is an autogenerated plain C Header file with basic types in\norder to allow an easy use of %s", component.LibraryName), + true); + + err = buildCTypesHeader(component, hTypesFile, component.NameSpace); + return err; +} + +func buildCTypesHeader (component ComponentDefinition, w LanguageWriter, NameSpace string) (error) { + w.Writeln("#ifndef __%s_TYPES_HEADER", strings.ToUpper (NameSpace)); + w.Writeln("#define __%s_TYPES_HEADER", strings.ToUpper (NameSpace)); + w.Writeln(""); + + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" General type definitions"); + w.Writeln("**************************************************************************************************************************/"); + + w.Writeln(""); + w.Writeln("typedef int %sResult;", NameSpace); + w.Writeln("typedef void * %sHandle;", NameSpace); + + w.Writeln(""); + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Version for %s", NameSpace); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + w.Writeln("#define %s_VERSION_MAJOR %d", strings.ToUpper (NameSpace), majorVersion(component.Version)); + w.Writeln("#define %s_VERSION_MINOR %d", strings.ToUpper (NameSpace), minorVersion(component.Version)); + w.Writeln("#define %s_VERSION_MICRO %d", strings.ToUpper (NameSpace), microVersion(component.Version)); + + w.Writeln(""); + + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Error constants for %s", NameSpace); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + w.Writeln("#define %s_SUCCESS 0", strings.ToUpper (NameSpace)); + + + for i := 0; i < len(component.Errors.Errors); i++ { + errorcode := component.Errors.Errors[i]; + w.Writeln("#define %s_ERROR_%s %d", strings.ToUpper (NameSpace), errorcode.Name, errorcode.Code); + } + + w.Writeln(""); + + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Declaration of handle classes "); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + + w.Writeln("typedef %sHandle %s_BaseClass;", NameSpace, NameSpace); + + for i := 0; i < len(component.Classes); i++ { + class := component.Classes[i]; + w.Writeln("typedef %sHandle %s_%s;", NameSpace, NameSpace, class.ClassName); + } + w.Writeln(""); + + if (len(component.Enums) > 0) { + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Declaration of enums"); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + + for i := 0; i < len(component.Enums); i++ { + enum := component.Enums[i]; + w.Writeln("enum e%s%s {", NameSpace, enum.Name); + + for j := 0; j < len(enum.Options); j++ { + + comma := ""; + if (j < len(enum.Options) - 1) { + comma = ","; + } + + option := enum.Options[j]; + w.Writeln(" e%s%s = %d%s", enum.Name, option.Name, option.Value, comma); + } + + w.Writeln("};"); + w.Writeln(""); + } + + + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Declaration of enum members for 4 byte struct alignment"); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + + for i := 0; i < len(component.Enums); i++ { + enum := component.Enums[i]; + w.Writeln("typedef union {"); + w.Writeln(" e%s%s m_enum;", NameSpace, enum.Name); + w.Writeln(" int m_code;"); + w.Writeln("} structEnum%s%s;", NameSpace, enum.Name); + w.Writeln(""); + } + } + + if len(component.Structs) > 0 { + + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Declaration of structs"); + w.Writeln("**************************************************************************************************************************/"); + w.Writeln(""); + + w.Writeln("#pragma pack (1)"); + w.Writeln(""); + + for i := 0; i < len(component.Structs); i++ { + structinfo := component.Structs[i]; + w.Writeln("typedef struct {"); + + for j := 0; j < len(structinfo.Members); j++ { + + member := structinfo.Members[j]; + + arraysuffix := ""; + if (member.Rows > 0) { + if (member.Columns > 0) { + arraysuffix = fmt.Sprintf ("[%d][%d]", member.Columns, member.Rows) + } else { + arraysuffix = fmt.Sprintf ("[%d]",member.Rows) + } + } + + switch (member.Type) { + case "uint8": + w.Writeln(" unsigned char m_%s%s;", member.Name, arraysuffix); + case "uint16": + w.Writeln(" unsigned short m_%s%s;", member.Name, arraysuffix); + case "uint32": + w.Writeln(" unsigned int m_%s%s;", member.Name, arraysuffix); + case "uint64": + w.Writeln(" unsigned long long m_%s%s;", member.Name, arraysuffix); + case "int8": + w.Writeln(" char m_%s%s;", member.Name, arraysuffix); + case "int16": + w.Writeln(" short m_%s%s;", member.Name, arraysuffix); + case "int32": + w.Writeln(" int m_%s%s;", member.Name, arraysuffix); + case "int64": + w.Writeln(" long long m_%s%s;", member.Name, arraysuffix); + case "bool": + w.Writeln(" bool m_%s%s;", member.Name, arraysuffix); + case "single": + w.Writeln(" float m_%s%s;", member.Name, arraysuffix); + case "double": + w.Writeln(" double m_%s%s;", member.Name, arraysuffix); + case "string": + return fmt.Errorf ("it is not possible for struct s%s%s to contain a string value", NameSpace, structinfo.Name); + case "handle": + return fmt.Errorf ("it is not possible for struct s%s%s to contain a handle value", NameSpace, structinfo.Name); + case "enum": + w.Writeln(" structEnum%s%s m_%s%s;", NameSpace, member.Class, member.Name, arraysuffix); + } + + + } + + w.Writeln("} s%s%s;", NameSpace, structinfo.Name); + w.Writeln(""); + } + + w.Writeln("#pragma pack ()"); + w.Writeln(""); + + } + + if len(component.Functions) > 0 { + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Declaration of function pointers "); + w.Writeln("**************************************************************************************************************************/"); + for i := 0; i < len(component.Functions); i++ { + functiontype := component.Functions[i] + returnType := "void" + parameters := "" + + w.Writeln(""); + w.Writeln("/**"); + w.Writeln("* %s%s - %s", NameSpace, functiontype.FunctionName, functiontype.FunctionDescription ) + w.Writeln("*") + for j := 0; j < len(functiontype.Params); j++ { + param := functiontype.Params[j] + + cParams, err := generateCParameter(param, "", functiontype.FunctionName, NameSpace) + if (err != nil) { + return err; + } + for _, cParam := range cParams { + w.Writeln(cParam.ParamComment); + } + + cParamTypeName, err := getCParameterTypeName(param.ParamType, NameSpace, param.ParamClass); + if (err != nil) { + return err; + } + if (parameters != "") { + parameters = parameters + ", " + } + if (param.ParamPass == "in") { + parameters = parameters + cParamTypeName + } else { + parameters = parameters + cParamTypeName + "*" + } + } + w.Writeln("*/"); + w.Writeln("typedef %s(*%s%s)(%s);", returnType, NameSpace, functiontype.FunctionName, parameters); + } + w.Writeln(""); + } + + w.Writeln("#endif // __%s_TYPES_HEADER", strings.ToUpper (NameSpace)); + + return nil; +} + +// CreateCHeader creates a C header file for the component's API +func CreateCHeader (component ComponentDefinition, CHeaderName string) (error) { + hfile, err := CreateLanguageFile(CHeaderName, " "); + if (err != nil) { + return err; + } + hfile.WriteCLicenseHeader (component, + fmt.Sprintf ("This is an autogenerated plain C Header file in order to allow an easy\n use of %s", component.LibraryName), + true); + err = buildCHeader (component, hfile, component.NameSpace, component.BaseName); + return err; +} + +func buildCHeader (component ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) (error) { + w.Writeln("#ifndef __%s_HEADER", strings.ToUpper (NameSpace)); + w.Writeln("#define __%s_HEADER", strings.ToUpper (NameSpace)); + w.Writeln(""); + w.Writeln("#ifdef __%s_DLL", strings.ToUpper (NameSpace)); + + w.Writeln("#ifdef WIN32"); + w.Writeln("#define %s_DECLSPEC __declspec (dllexport)", strings.ToUpper (NameSpace)); + w.Writeln("#else // WIN32"); + w.Writeln("#define %s_DECLSPEC __attribute__((visibility(\"default\")))", strings.ToUpper (NameSpace)); + w.Writeln("#endif // WIN32"); + + w.Writeln("#else // __%s_DLL", strings.ToUpper (NameSpace)); + w.Writeln("#define %s_DECLSPEC", strings.ToUpper (NameSpace)); + w.Writeln("#endif // __%s_DLL", strings.ToUpper (NameSpace)); + w.Writeln(""); + + w.Writeln("#include \"%s_types.h\"", BaseName); + w.Writeln(""); + + w.Writeln("extern \"C\" {"); + + for i := 0; i < len(component.Classes); i++ { + class := component.Classes[i]; + + w.Writeln(""); + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Class definition for %s", class.ClassName); + w.Writeln("**************************************************************************************************************************/"); + + for j := 0; j < len(class.Methods); j++ { + method := class.Methods[j]; + WriteCMethod (method, w, NameSpace, class.ClassName, false, false); + } + } + + + w.Writeln(""); + w.Writeln("/*************************************************************************************************************************"); + w.Writeln(" Global functions"); + w.Writeln("**************************************************************************************************************************/"); + + global := component.Global; + for j := 0; j < len(global.Methods); j++ { + method := global.Methods[j]; + err := WriteCMethod (method, w, NameSpace, "Wrapper", true, false); + if (err != nil) { + return err; + } + } + + w.Writeln(""); + w.Writeln("}"); + w.Writeln(""); + w.Writeln("#endif // __%s_HEADER", strings.ToUpper (NameSpace)); + w.Writeln(""); + + return nil; +} + + +// GetCExportName How do we name the exports in the plain C DLL +func GetCExportName (NameSpace string, ClassName string, method ComponentDefinitionMethod, isGlobal bool) (string) { + CMethodName := ""; + if isGlobal { + CMethodName = fmt.Sprintf("%s_%s%s", strings.ToLower(NameSpace), strings.ToLower(method.MethodName), method.DLLSuffix) + } else { + CMethodName = fmt.Sprintf("%s_%s_%s%s", strings.ToLower(NameSpace), strings.ToLower(ClassName), strings.ToLower(method.MethodName), method.DLLSuffix) + } + + return CMethodName; +} + + +// WriteCMethod writes a method as a C funtion +func WriteCMethod (method ComponentDefinitionMethod, w LanguageWriter, NameSpace string, ClassName string, isGlobal bool, writeCallbacks bool) (error) { + + CMethodName := ""; + CCallbackName := ""; + parameters := ""; + if (isGlobal) { + CMethodName = fmt.Sprintf ("%s_%s%s", strings.ToLower (NameSpace), strings.ToLower (method.MethodName), method.DLLSuffix); + CCallbackName = fmt.Sprintf ("P%s%sPtr", NameSpace, method.MethodName); + } else { + CMethodName = fmt.Sprintf ("%s_%s_%s%s", strings.ToLower (NameSpace), strings.ToLower (ClassName), strings.ToLower (method.MethodName), method.DLLSuffix); + CCallbackName = fmt.Sprintf ("P%s%s_%sPtr", NameSpace, ClassName, method.MethodName); + parameters = fmt.Sprintf ("%s_%s p%s", NameSpace, ClassName, ClassName); + } + + w.Writeln(""); + w.Writeln("/**"); + w.Writeln("* %s", method.MethodDescription); + w.Writeln("*"); + if (!isGlobal) { + w.Writeln("* @param[in] p%s - %s instance.", ClassName, ClassName); + } + + + for k := 0; k < len(method.Params); k++ { + param := method.Params [k]; + + cParams, err := generateCParameter(param, ClassName, method.MethodName, NameSpace); + if (err != nil) { + return err; + } + + for _, cParam := range cParams { + w.Writeln(cParam.ParamComment); + if (parameters != "") { + parameters = parameters + ", "; + } + parameters = parameters + cParam.ParamType + " " + cParam.ParamName; + } + + } + + w.Writeln("* @return error code or 0 (success)"); + w.Writeln("*/"); + + if (writeCallbacks) { + w.Writeln("typedef %sResult (*%s) (%s);", NameSpace, CCallbackName, parameters); + } else { + w.Writeln("%s_DECLSPEC %sResult %s (%s);", strings.ToUpper(NameSpace), NameSpace, CMethodName, parameters); + } + + return nil; +} + + +func getCParameterTypeName(ParamTypeName string, NameSpace string, ParamClass string)(string, error) { + cParamTypeName := ""; + switch (ParamTypeName) { + case "uint8": + cParamTypeName = "unsigned char"; + + case "uint16": + cParamTypeName = "unsigned short"; + + case "uint32": + cParamTypeName = "unsigned int"; + + case "uint64": + cParamTypeName = "unsigned long long"; + + case "int8": + cParamTypeName = "char"; + + case "int16": + cParamTypeName = "short"; + + case "int32": + cParamTypeName = "int"; + + case "int64": + cParamTypeName = "long long"; + + case "bool": + cParamTypeName = "bool"; + + case "single": + cParamTypeName = "float"; + + case "double": + cParamTypeName = "double"; + + case "string": + cParamTypeName = "char *"; + + case "enum": + cParamTypeName = fmt.Sprintf ("e%s%s", NameSpace, ParamClass); + + case "struct": + cParamTypeName = fmt.Sprintf ("s%s%s *", NameSpace, ParamClass); + + case "basicarray": + basicTypeName, err := getCParameterTypeName(ParamClass, NameSpace, ""); + if (err != nil) { + return "", err; + } + cParamTypeName = fmt.Sprintf ("%s *", basicTypeName); + + case "structarray": + cParamTypeName = fmt.Sprintf ("s%s%s *", NameSpace, ParamClass) + + case "handle": + cParamTypeName = fmt.Sprintf ("%s_%s", NameSpace, ParamClass) + + case "functiontype": + cParamTypeName = fmt.Sprintf ("%s%s", NameSpace, ParamClass) + + default: + return "", fmt.Errorf ("invalid parameter type \"%s\" for C-parameter", ParamTypeName); + } + + return cParamTypeName, nil; +} + +// CParameter is a handy representation of a function parameter in C +type CParameter struct { + ParamType string + ParamName string + ParamComment string +} + + +func generateCParameter(param ComponentDefinitionParam, className string, methodName string, NameSpace string) ([]CParameter, error) { + cParams := make([]CParameter,1) + cParamTypeName, err := getCParameterTypeName(param.ParamType, NameSpace, param.ParamClass); + if (err != nil) { + return nil, err; + } + + switch (param.ParamPass) { + case "in": + switch (param.ParamType) { + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "n" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "bool": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "b" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "single": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "f" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "double": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "d" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "string": + cParams[0].ParamType = "const " + cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "enum": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "e" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "struct": + cParams[0].ParamType = "const " + cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "basicarray", "structarray": + cParams = make([]CParameter,2) + cParams[0].ParamType = "const unsigned int"; + cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + + cParams[1].ParamType = "const " + cParamTypeName; + cParams[1].ParamName = "p" + param.ParamName + "Buffer"; + cParams[1].ParamComment = fmt.Sprintf("* @param[in] %s - %s buffer of %s", cParams[1].ParamName, param.ParamClass, param.ParamDescription); + + case "handle": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "functiontype": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + + default: + return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); + } + + case "out", "return": + + switch (param.ParamType) { + + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double", "enum": + cParams[0].ParamType = cParamTypeName + " *"; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "struct": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + + case "basicarray", "structarray": + cParams = make([]CParameter,3) + cParams[0].ParamType = "const unsigned int"; + cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + + cParams[1].ParamType = "unsigned int *"; + cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + + case "string": + cParams = make([]CParameter,3) + cParams[0].ParamType = "const unsigned int"; + cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - size of the buffer (including trailing 0)", cParams[0].ParamName); + + cParams[1].ParamType = "unsigned int *"; + cParams[1].ParamName = "p" + param.ParamName + "NeededChars"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written bytes, or needed buffer size.", cParams[1].ParamName); + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s, may be NULL", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + + case "handle": + cParams[0].ParamType = cParamTypeName + " *"; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + + default: + return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); + } + + default: + return nil, fmt.Errorf ("invalid method parameter passing \"%s\" for %s.%s (%s)", param.ParamPass, className, methodName, param.ParamName); + } + + return cParams, nil; +} + +// GenerateCParameters generates an array of cParameters for a method +func GenerateCParameters(method ComponentDefinitionMethod, className string, NameSpace string) ([]CParameter, error) { + parameters := []CParameter{}; + for k := 0; k < len(method.Params); k++ { + param := method.Params [k]; + + cParam, err := generateCParameter(param, className, method.MethodName, NameSpace); + if err != nil { + return nil, err; + } + parameters = append(parameters, cParam...); + } + + return parameters, nil; +} \ No newline at end of file diff --git a/Source/languagepascal.go b/Source/languagepascal.go new file mode 100644 index 00000000..ace2daeb --- /dev/null +++ b/Source/languagepascal.go @@ -0,0 +1,609 @@ +/*++ + +Copyright (C) 2018 Autodesk Inc. (Original Author) + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation +and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--*/ + +////////////////////////////////////////////////////////////////////////////////////////////////////// +// languagepascal.go +// functions to generate the Pascal-layer of a library's API (can be used in bindings or implementation) +////////////////////////////////////////////////////////////////////////////////////////////////////// + +package main + +import ( + "fmt" + "strings" +) + + + +func writePascalBaseTypeDefinitions(componentdefinition ComponentDefinition, w LanguageWriter, NameSpace string, BaseName string) error { + + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Version definition for %s", NameSpace); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + w.Writeln ("const"); + w.Writeln (" %s_VERSION_MAJOR = %d;", strings.ToUpper (NameSpace), majorVersion(componentdefinition.Version)); + w.Writeln (" %s_VERSION_MINOR = %d;", strings.ToUpper (NameSpace), minorVersion(componentdefinition.Version)); + w.Writeln (" %s_VERSION_MICRO = %d;", strings.ToUpper (NameSpace), microVersion(componentdefinition.Version)); + w.Writeln (""); + w.Writeln (""); + + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" General type definitions"); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln ("") + + w.Writeln ("type"); + w.Writeln (" T%sResult = Cardinal;", NameSpace); + w.Writeln (" T%sHandle = Pointer;", NameSpace); + w.Writeln ("") + + w.Writeln (" P%sResult = ^T%sResult;", NameSpace, NameSpace); + w.Writeln (" P%sHandle = ^T%sHandle;", NameSpace, NameSpace); + w.Writeln ("") + + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Error Constants for %s", NameSpace); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + w.Writeln ("const"); + w.Writeln (" %s_SUCCESS = 0;", strings.ToUpper (NameSpace)); + + for i := 0; i < len(componentdefinition.Errors.Errors); i++ { + errorcode := componentdefinition.Errors.Errors[i]; + w.Writeln (" %s_ERROR_%s = %d;", strings.ToUpper (NameSpace), errorcode.Name, errorcode.Code); + } + w.Writeln (""); + + if (len(componentdefinition.Enums) > 0) { + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Declaration of enums"); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + w.Writeln ("type"); + w.Writeln (""); + + for i := 0; i < len(componentdefinition.Enums); i++ { + enum := componentdefinition.Enums[i]; + w.Writeln (" T%s%s = (", NameSpace, enum.Name); + + for j := 0; j < len(enum.Options); j++ { + comma := ""; + if (j < len(enum.Options) - 1) { + comma = ","; + } + option := enum.Options[j]; + w.Writeln (" e%s%s%s", enum.Name, option.Name, comma); + } + + w.Writeln ( " );"); + w.Writeln ( ""); + } + } + + if len(componentdefinition.Structs) > 0 { + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Declaration of structs"); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + w.Writeln ("type"); + w.Writeln (""); + + for i := 0; i < len(componentdefinition.Structs); i++ { + structinfo := componentdefinition.Structs[i]; + w.Writeln ( " P%s%s = ^T%s%s;", NameSpace, structinfo.Name, NameSpace, structinfo.Name); + w.Writeln ( " T%s%s = packed record", NameSpace, structinfo.Name); + + for j := 0; j < len(structinfo.Members); j++ { + element := structinfo.Members[j]; + arrayprefix := ""; + if (element.Rows > 0) { + if (element.Columns > 0) { + arrayprefix = fmt.Sprintf ("array [0..%d, 0..%d] of ", element.Columns - 1, element.Rows - 1) + } else { + arrayprefix = fmt.Sprintf ("array [0..%d] of ",element.Rows - 1) + } + } + + switch (element.Type) { + case "uint8": + w.Writeln ( " F%s: %sByte;", element.Name, arrayprefix); + case "uint16": + w.Writeln ( " F%s: %sWord;", element.Name, arrayprefix); + case "uint32": + w.Writeln ( " F%s: %sCardinal;", element.Name, arrayprefix); + case "uint64": + w.Writeln ( " F%s: %sQWord;", element.Name, arrayprefix); + case "int8": + w.Writeln ( " F%s: %sSmallInt;", element.Name, arrayprefix); + case "int16": + w.Writeln ( " F%s: %sShortInt;", element.Name, arrayprefix); + case "int32": + w.Writeln ( " F%s: %sInteger;", element.Name, arrayprefix); + case "int64": + w.Writeln ( " F%s: %sInt64;", element.Name, arrayprefix); + case "bool": + w.Writeln ( " F%s: %sCardinal;", element.Name, arrayprefix); + case "single": + w.Writeln ( " F%s: %sSingle;", element.Name, arrayprefix); + case "double": + w.Writeln ( " F%s: %sDouble;", element.Name, arrayprefix); + case "string": + return fmt.Errorf ("it is not possible for struct s%s%s to contain a string value", NameSpace, structinfo.Name); + case "handle": + return fmt.Errorf ("it is not possible for struct s%s%s to contain a handle value", NameSpace, structinfo.Name); + case "enum": + w.Writeln ( " F%s: %sInteger;", element.Name, arrayprefix); + } + } + + w.Writeln (" end;"); + w.Writeln (""); + } + + w.Writeln ( ""); + + if len(componentdefinition.Functions) > 0 { + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Declaration of function types"); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + for i := 0; i < len(componentdefinition.Functions); i++ { + funcinfo := componentdefinition.Functions[i]; + arguments := "" + for j := 0; j<len(funcinfo.Params); j++ { + param := funcinfo.Params[j] + if (arguments != "") { + arguments = arguments + "; " + } + cParams, err := generatePlainPascalParameter(param, "", funcinfo.FunctionName, NameSpace) + if (err != nil) { + return err + } + arguments = arguments + cParams[0].ParamConvention + cParams[0].ParamName + ": " + cParams[0].ParamType + } + + w.Writeln (" P%s_%s = function(%s): Integer;", NameSpace, funcinfo.FunctionName, arguments); + } + } + + w.Writeln ( ""); + + + w.Writeln ("(*************************************************************************************************************************"); + w.Writeln (" Declaration of struct arrays"); + w.Writeln ("**************************************************************************************************************************)"); + w.Writeln (""); + + for i := 0; i < len(componentdefinition.Structs); i++ { + structinfo := componentdefinition.Structs[i]; + w.Writeln (" ArrayOf%s%s = array of T%s%s;", NameSpace, structinfo.Name, NameSpace, structinfo.Name); + } + + w.Writeln (""); + } + return nil; +} + +func getPascalParameterType(ParamTypeName string, NameSpace string, ParamClass string, isPlain bool, isImplementation bool)(string, error) { + PascalParamTypeName := ""; + switch (ParamTypeName) { + case "uint8": + PascalParamTypeName = "Byte"; + + case "uint16": + PascalParamTypeName = "Word"; + + case "uint32": + PascalParamTypeName = "Cardinal"; + + case "uint64": + PascalParamTypeName = "QWord"; + + case "int8": + PascalParamTypeName = "ShortInt"; + + case "int16": + PascalParamTypeName = "SmallInt"; + + case "int32": + PascalParamTypeName = "Integer"; + + case "int64": + PascalParamTypeName = "Int64"; + + case "bool": + if isPlain { + PascalParamTypeName = "Cardinal"; + } else { + PascalParamTypeName = "Boolean"; + } + + case "single": + PascalParamTypeName = "Single"; + + case "double": + PascalParamTypeName = "Double"; + + case "string": + if isPlain { + PascalParamTypeName = "PAnsiChar"; + } else { + PascalParamTypeName = "String"; + } + + case "enum": + if isPlain { + PascalParamTypeName = fmt.Sprintf ("Integer"); + } else { + PascalParamTypeName = fmt.Sprintf ("T%s%s", NameSpace, ParamClass); + } + + case "functiontype": + if isPlain { + PascalParamTypeName = fmt.Sprintf ("P%s_%s", NameSpace, ParamClass); + } else { + PascalParamTypeName = fmt.Sprintf ("P%s_%s", NameSpace, ParamClass); + } + + case "struct": + if isPlain { + PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass); + } else { + PascalParamTypeName = fmt.Sprintf ("T%s%s", NameSpace, ParamClass); + } + + case "basicarray": + basicTypeName, err := getPascalParameterType(ParamClass, NameSpace, "", isPlain, isImplementation); + if (err != nil) { + return "", err; + } + + if isPlain { + PascalParamTypeName = fmt.Sprintf ("P%s", basicTypeName); + } else { + if isImplementation { + PascalParamTypeName = fmt.Sprintf ("P%s", basicTypeName); + } else { + PascalParamTypeName = fmt.Sprintf ("T%sDynArray", basicTypeName); + } + } + + case "structarray": + if isPlain { + PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass) + } else { + if isImplementation { + PascalParamTypeName = fmt.Sprintf ("P%s%s", NameSpace, ParamClass) + } else { + PascalParamTypeName = fmt.Sprintf ("ArrayOf%s%s", NameSpace, ParamClass); + } + } + + case "handle": + if isPlain { + PascalParamTypeName = fmt.Sprintf ("T%sHandle", NameSpace) + } else { + if isImplementation { + PascalParamTypeName = "TObject"; + } else { + PascalParamTypeName = fmt.Sprintf ("T%s%s", NameSpace, ParamClass); + } + } + + default: + return "", fmt.Errorf ("invalid parameter type \"%s\" for Pascal parameter", ParamTypeName); + } + + return PascalParamTypeName, nil; +} + + +type pascalParameter struct { + ParamType string + ParamName string + ParamComment string + ParamConvention string + ParamTypeNoConvention string +} + +func generatePlainPascalParameter(param ComponentDefinitionParam, className string, methodName string, NameSpace string) ([]pascalParameter, error) { + cParams := make([]pascalParameter,1) + cParamTypeName, err := getPascalParameterType(param.ParamType, NameSpace, param.ParamClass, true, false); + if (err != nil) { + return nil, err; + } + + switch (param.ParamPass) { + case "in": + switch (param.ParamType) { + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "n" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "bool": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "b" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "single": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "f" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "double": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "d" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "string": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "enum": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "e" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "struct": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "basicarray", "structarray": + cParams = make([]pascalParameter,2) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "Count"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = cParamTypeName; + cParams[1].ParamName = "p" + param.ParamName + "Buffer"; + cParams[1].ParamComment = fmt.Sprintf("* @param[in] %s - %s buffer of %s", cParams[1].ParamName, param.ParamClass, param.ParamDescription); + cParams[1].ParamConvention = "const "; + cParams[1].ParamTypeNoConvention = cParams[1].ParamType; + + case "functiontype": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + case "handle": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + default: + return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); + } + + case "out": + + switch (param.ParamType) { + + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double", "enum": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName; + + case "struct": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; + + case "basicarray": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "Count"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "structarray": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "Count"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "string": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - size of the buffer (including trailing 0)", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededChars"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written bytes, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = "PAnsiChar"; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s, may be NULL", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "handle": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; + + default: + return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); + } + + case "return": + + switch (param.ParamType) { + + case "uint8", "uint16", "uint32", "uint64", "int8", "int16", "int32", "int64", "bool", "single", "double", "enum": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName; + + case "struct": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; + + case "basicarray": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "Count"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "structarray": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "Count"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - Number of elements in buffer", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededCount"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written elements, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = cParamTypeName; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "string": + cParams = make([]pascalParameter,3) + cParams[0].ParamType = "Cardinal"; + cParams[0].ParamName = "n" + param.ParamName + "BufferSize"; + cParams[0].ParamComment = fmt.Sprintf("* @param[in] %s - size of the buffer (including trailing 0)", cParams[0].ParamName); + cParams[0].ParamConvention = "const "; + cParams[0].ParamTypeNoConvention = cParams[0].ParamType; + + cParams[1].ParamType = "Cardinal"; + cParams[1].ParamName = "p" + param.ParamName + "NeededChars"; + cParams[1].ParamComment = fmt.Sprintf("* @param[out] %s - will be filled with the count of the written bytes, or needed buffer size.", cParams[1].ParamName); + cParams[1].ParamConvention = "out "; + cParams[1].ParamTypeNoConvention = "PCardinal"; + + cParams[2].ParamType = "PAnsiChar"; + cParams[2].ParamName = "p" + param.ParamName + "Buffer"; + cParams[2].ParamComment = fmt.Sprintf("* @param[out] %s - %s buffer of %s, may be NULL", cParams[2].ParamName, param.ParamClass, param.ParamDescription); + cParams[2].ParamConvention = ""; + cParams[2].ParamTypeNoConvention = cParams[2].ParamType; + + case "handle": + cParams[0].ParamType = cParamTypeName; + cParams[0].ParamName = "p" + param.ParamName; + cParams[0].ParamComment = fmt.Sprintf("* @param[out] %s - %s", cParams[0].ParamName, param.ParamDescription); + cParams[0].ParamConvention = "out "; + cParams[0].ParamTypeNoConvention = "P" + cParamTypeName[1:]; + + default: + return nil, fmt.Errorf ("invalid method parameter type \"%s\" for %s.%s (%s)", param.ParamType, className, methodName, param.ParamName); + } + + default: + return nil, fmt.Errorf ("invalid method parameter passing \"%s\" for %s.%s (%s)", param.ParamPass, className, methodName, param.ParamName); + } + + return cParams, nil; +} \ No newline at end of file diff --git a/Source/languagewriter.go b/Source/languagewriter.go index 51f449da..4997ee76 100644 --- a/Source/languagewriter.go +++ b/Source/languagewriter.go @@ -42,11 +42,31 @@ import ( // LanguageWriter is a wrapper around a io.Writer that handles indentation type LanguageWriter struct { + Indentation int IndentString string - Writer io.Writer + Writer io.Writer CurrentLine string } +func max(x, y int) int { + if x > y { + return x + } + return y +} + +// AddIndentationLevel adds number of indentation the writers output +func (writer *LanguageWriter) AddIndentationLevel (levels int) (error) { + writer.Indentation = max(writer.Indentation + levels, 0) + return nil +} + +// ResetIndentationLevel adds indentation to all output +func (writer *LanguageWriter) ResetIndentationLevel () (error) { + writer.Indentation = 0 + return nil +} + // Writeln formats a string and writes it to a line. Pairs of leadin spaces will be replaced by the indent IndentString. func (writer *LanguageWriter) Writeln (format string, a ...interface{}) (int, error) { @@ -57,11 +77,10 @@ func (writer *LanguageWriter) Writeln (format string, a ...interface{}) (int, er } else { break; } - } - + } leadingIndents := leadingSpaces / 2; - indentedFormat := strings.Repeat (writer.IndentString, leadingIndents) + format[leadingIndents * 2:]; + indentedFormat := strings.Repeat (writer.IndentString, leadingIndents + writer.Indentation) + format[leadingIndents * 2:]; return fmt.Fprintf (writer.Writer, indentedFormat + "\n", a...); } @@ -127,6 +146,7 @@ func WritePascalLicenseHeader (w io.Writer, component ComponentDefinition, abstr // writeLicenseHeaderEx writes a license header into a writer. func writeLicenseHeaderEx (w io.Writer, component ComponentDefinition, abstract string, includeVersion bool, CommandStart string, CommandEnd string) { + ACTVersion := component.ACTVersion; version := component.Version; copyright := component.Copyright; year := component.Year; @@ -139,11 +159,14 @@ func writeLicenseHeaderEx (w io.Writer, component ComponentDefinition, abstract line := component.License.Lines[i]; fmt.Fprintf (w, "%s\n", line.Value); } - fmt.Fprintf (w, "\n"); + if (includeVersion) { + fmt.Fprintf (w, "This file has been generated by the Automatic Component Toolkit (ACT) version %s.\n", ACTVersion) + fmt.Fprintf (w, "\n"); + } fmt.Fprintf (w, "Abstract: %s\n", abstract); if (includeVersion) { - fmt.Fprintf (w, "Interface version: %d.%d.%d\n", majorVersion(version), minorVersion(version), microVersion(version)) + fmt.Fprintf (w, "\nInterface version: %d.%d.%d\n", majorVersion(version), minorVersion(version), microVersion(version)) } fmt.Fprintf (w, "\n"); fmt.Fprintf (w, "%s\n", CommandEnd); @@ -156,7 +179,8 @@ func CreateLanguageFile (fileName string, indentString string) (LanguageWriter, var result LanguageWriter; var err error; - result.IndentString = indentString; + result.IndentString = indentString + result.Indentation = 0 result.Writer, err = os.Create(fileName) if err != nil { return result, err; diff --git a/build.bat b/build.bat index cea4eabb..a2c93974 100644 --- a/build.bat +++ b/build.bat @@ -1,6 +1,6 @@ @echo off cd Source -set Sources=actutils.go automaticcomponenttoolkit.go buildbindingcdynamic.go buildbindingcpp.go buildbindinggo.go buildbindingnode.go buildbindingpascal.go buildbindingpython.go buildimplementationcpp.go buildimplementationpascal.go componentdefinition.go languagewriter.go lanugagec.go +set Sources=actutils.go automaticcomponenttoolkit.go buildbindingcdynamic.go buildbindingcpp.go buildbindinggo.go buildbindingnode.go buildbindingpascal.go buildbindingpython.go buildimplementationcpp.go buildimplementationpascal.go componentdefinition.go languagewriter.go languagec.go languagepascal.go set GOOS=windows set GOARCH=amd64 go build -o ..\act.exe %Sources%