From fbb1b0e4647dfd974fa5bef4670d2d4411f81c37 Mon Sep 17 00:00:00 2001 From: Yu Yang Date: Tue, 3 Jan 2017 12:49:05 +0800 Subject: [PATCH] Start Doing C-API for predict. --- paddle/CMakeLists.txt | 2 +- paddle/capi/Arguments.cpp | 49 +++++++++++++++ paddle/capi/CMakeLists.txt | 47 ++++++++++++++ paddle/capi/Matrix.cpp | 61 +++++++++++++++++++ paddle/capi/PaddleCAPI.h | 54 ++++++++++++++++ paddle/capi/PaddleCAPIPrivate.h | 27 ++++++++ paddle/capi/Vector.cpp | 26 ++++++++ paddle/capi/config.h.in | 6 ++ paddle/capi/tests/CMakeLists.txt | 15 +++++ paddle/capi/tests/test_Arguments.cpp | 54 ++++++++++++++++ paddle/capi/tests/test_Matrix.cpp | 33 ++++++++++ paddle/capi/tests/test_Vector.cpp | 11 ++++ paddle/utils/ForceLink.h | 46 ++++++++++++++ paddle/utils/tests/CMakeLists.txt | 8 +++ paddle/utils/tests/test_ClassRegistrar.cpp | 27 ++++++++ .../tests/test_ClassRegistrarGlobals.cpp | 16 +++++ paddle/utils/tests/test_ClassRegistrarLib.cpp | 31 ++++++++++ paddle/utils/tests/test_ClassRegistrarLib.h | 23 +++++++ 18 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 paddle/capi/Arguments.cpp create mode 100644 paddle/capi/CMakeLists.txt create mode 100644 paddle/capi/Matrix.cpp create mode 100644 paddle/capi/PaddleCAPI.h create mode 100644 paddle/capi/PaddleCAPIPrivate.h create mode 100644 paddle/capi/Vector.cpp create mode 100644 paddle/capi/config.h.in create mode 100644 paddle/capi/tests/CMakeLists.txt create mode 100644 paddle/capi/tests/test_Arguments.cpp create mode 100644 paddle/capi/tests/test_Matrix.cpp create mode 100644 paddle/capi/tests/test_Vector.cpp create mode 100644 paddle/utils/ForceLink.h create mode 100644 paddle/utils/tests/test_ClassRegistrar.cpp create mode 100644 paddle/utils/tests/test_ClassRegistrarGlobals.cpp create mode 100644 paddle/utils/tests/test_ClassRegistrarLib.cpp create mode 100644 paddle/utils/tests/test_ClassRegistrarLib.h diff --git a/paddle/CMakeLists.txt b/paddle/CMakeLists.txt index 503024cff3..b3f3b2fbce 100644 --- a/paddle/CMakeLists.txt +++ b/paddle/CMakeLists.txt @@ -8,7 +8,7 @@ add_subdirectory(gserver) add_subdirectory(pserver) add_subdirectory(trainer) add_subdirectory(scripts) - +add_subdirectory(capi) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/setup.py.in ${CMAKE_CURRENT_SOURCE_DIR}/setup.py) diff --git a/paddle/capi/Arguments.cpp b/paddle/capi/Arguments.cpp new file mode 100644 index 0000000000..cf773a6587 --- /dev/null +++ b/paddle/capi/Arguments.cpp @@ -0,0 +1,49 @@ +#include "PaddleCAPI.h" +#include "PaddleCAPIPrivate.h" + +#define cast(v) paddle::capi::cast(v) + +extern "C" { +int PDArgsCreateNone(PD_Arguments* args) { + auto ptr = new paddle::capi::CArguments(); + *args = ptr; + return PD_NO_ERROR; +} + +int PDArgsDestroy(PD_Arguments args) { + if (args == nullptr) return PD_NULLPTR; + delete cast(args); + return PD_NO_ERROR; +} + +int PDArgsGetSize(PD_Arguments args, uint64_t* size) { + if (args == nullptr || size == nullptr) return PD_NULLPTR; + *size = cast(args)->args.size(); + return PD_NO_ERROR; +} + +int PDArgsResize(PD_Arguments args, uint64_t size) { + if (args == nullptr) return PD_NULLPTR; + cast(args)->args.resize(size); + return PD_NO_ERROR; +} + +int PDArgsSetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) { + if (args == nullptr || mat == nullptr) return PD_NULLPTR; + auto m = paddle::capi::cast(mat); + if (m->mat == nullptr) return PD_NULLPTR; + auto a = cast(args); + if (ID >= a->args.size()) return PD_OUT_OF_RANGE; + a->args[ID].value = m->mat; + return PD_NO_ERROR; +} + +int PDArgsGetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat) { + if (args == nullptr || mat == nullptr) return PD_NULLPTR; + auto m = paddle::capi::cast(mat); + auto a = cast(args); + if (ID >= a->args.size()) return PD_OUT_OF_RANGE; + m->mat = a->args[ID].value; + return PD_NO_ERROR; +} +} diff --git a/paddle/capi/CMakeLists.txt b/paddle/capi/CMakeLists.txt new file mode 100644 index 0000000000..6162267dab --- /dev/null +++ b/paddle/capi/CMakeLists.txt @@ -0,0 +1,47 @@ +if (WITH_DOUBLE) + set(PADDLE_FLOAT_TYPE double) +else () + set(PADDLE_FLOAT_TYPE float) +endif() + +configure_file(config.h.in config.h @ONLY) + +set(CAPI_HEADER + PaddleCAPI.h) +set(CAPI_PRIVATE_HEADER + PaddleCAPIPrivate.h) +file(GLOB CAPI_SOURCES *.cpp) + +add_library(paddle_capi SHARED ${CAPI_SOURCES}) + +target_include_directories(paddle_capi PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +add_dependencies(paddle_capi gen_proto_cpp) + +target_link_libraries(paddle_capi + paddle_gserver + paddle_function + paddle_pserver + paddle_trainer_lib + paddle_network + paddle_math + paddle_utils + paddle_parameter + paddle_proto + paddle_cuda + ${PROTOBUF_LIBRARY} + ${LIBGLOG_LIBRARY} + ${GFLAGS_LIBRARIES} + ${CMAKE_THREAD_LIBS_INIT} + ${CBLAS_LIBS} + ${ZLIB_LIBRARIES} + ${INTERAL_LIBS} + ${CMAKE_DL_LIBS}) + + +set(PADDLE_CAPI_INC_PATH + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}) + +if (WITH_TESTING) + add_subdirectory(tests) +endif() diff --git a/paddle/capi/Matrix.cpp b/paddle/capi/Matrix.cpp new file mode 100644 index 0000000000..71598b1714 --- /dev/null +++ b/paddle/capi/Matrix.cpp @@ -0,0 +1,61 @@ +#include "PaddleCAPI.h" +#include "PaddleCAPIPrivate.h" +#include "hl_cuda.h" + +#define cast(v) paddle::capi::cast(v) +extern "C" { +int PDMatCreate(PD_Matrix* mat, uint64_t height, uint64_t width, bool useGpu) { + auto ptr = new paddle::capi::CMatrix(); + ptr->mat = paddle::Matrix::create(height, width, false, useGpu); + *mat = ptr; + return PD_NO_ERROR; +} + +int PDMatCreateNone(PD_Matrix* mat) { + auto ptr = new paddle::capi::CMatrix(); + *mat = ptr; + return PD_NO_ERROR; +} + +int PDMatDestroy(PD_Matrix mat) { + if (mat == nullptr) return PD_NULLPTR; + auto ptr = cast(mat); + delete ptr; + return PD_NO_ERROR; +} + +int PDMatCopyToRow(PD_Matrix mat, uint64_t rowID, pd_real* rowArray) { + if (mat == nullptr) return PD_NULLPTR; + auto ptr = cast(mat); + if (ptr->mat == nullptr) return PD_NULLPTR; + if (rowID >= ptr->mat->getHeight()) return PD_OUT_OF_RANGE; + paddle::real* buf = ptr->mat->getRowBuf(rowID); + size_t width = ptr->mat->getWidth(); +#ifndef PADDLE_ONLY_CPU + hl_memcpy(buf, rowArray, sizeof(paddle::real) * width); +#else + std::copy(rowArray, rowArray + width, buf); +#endif + return PD_NO_ERROR; +} + +int PDMatGetRow(PD_Matrix mat, uint64_t rowID, pd_real** rawRowBuffer) { + if (mat == nullptr) return PD_NULLPTR; + auto ptr = cast(mat); + if (ptr->mat == nullptr) return PD_NULLPTR; + if (rowID >= ptr->mat->getHeight()) return PD_OUT_OF_RANGE; + *rawRowBuffer = ptr->mat->getRowBuf(rowID); + return PD_NO_ERROR; +} + +int PDMatGetShape(PD_Matrix mat, uint64_t* height, uint64_t* width) { + if (mat == nullptr) return PD_NULLPTR; + if (height != nullptr) { + *height = cast(mat)->mat->getHeight(); + } + if (width != nullptr) { + *width = cast(mat)->mat->getWidth(); + } + return PD_NO_ERROR; +} +} diff --git a/paddle/capi/PaddleCAPI.h b/paddle/capi/PaddleCAPI.h new file mode 100644 index 0000000000..2eff0bc7da --- /dev/null +++ b/paddle/capi/PaddleCAPI.h @@ -0,0 +1,54 @@ +#ifndef __PADDLE_PADDLE_CAPI_PADDLECAPI_H_INCLUDED__ +#define __PADDLE_PADDLE_CAPI_PADDLECAPI_H_INCLUDED__ +#include +#include +#include "config.h" +#ifdef __cplusplus +extern "C" { +#endif + +#define PD_NO_ERROR 0 +#define PD_NULLPTR 1 +#define PD_OUT_OF_RANGE 2 +#define PD_UNDEFINED_ERROR -1 + +typedef void* PD_Vector; + +int PDVecCreate(PD_Vector* vec, uint64_t size, bool useGpu); + +int PDVecDestroy(PD_Vector vec); + +int PDVecIsSparse(PD_Vector vec, bool* isSparse); + +typedef void* PD_Matrix; + +int PDMatCreate(PD_Matrix* mat, uint64_t height, uint64_t width, bool useGpu); + +int PDMatDestroy(PD_Matrix mat); + +int PDMatCopyToRow(PD_Matrix mat, uint64_t rowID, pd_real* rowArray); + +int PDMatGetRow(PD_Matrix mat, uint64_t rowID, pd_real** rawRowBuffer); + +int PDMatCreateNone(PD_Matrix* mat); + +int PDMatGetShape(PD_Matrix mat, uint64_t* height, uint64_t* width); + +typedef void* PD_Arguments; + +int PDArgsCreateNone(PD_Arguments* args); + +int PDArgsDestroy(PD_Arguments args); + +int PDArgsGetSize(PD_Arguments args, uint64_t* size); + +int PDArgsResize(PD_Arguments args, uint64_t size); + +int PDArgsSetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat); + +int PDArgsGetValue(PD_Arguments args, uint64_t ID, PD_Matrix mat); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/paddle/capi/PaddleCAPIPrivate.h b/paddle/capi/PaddleCAPIPrivate.h new file mode 100644 index 0000000000..efec60fbb6 --- /dev/null +++ b/paddle/capi/PaddleCAPIPrivate.h @@ -0,0 +1,27 @@ +#include "PaddleCAPI.h" +#include "paddle/math/Matrix.h" +#include "paddle/math/Vector.h" +#include "paddle/parameter/Argument.h" +#pragma once + +namespace paddle { +namespace capi { + +struct CVector { + VectorPtr vec; +}; + +struct CMatrix { + MatrixPtr mat; +}; + +struct CArguments { + std::vector args; +}; + +template +inline T* cast(void* ptr) { + return reinterpret_cast(ptr); +} +} +} diff --git a/paddle/capi/Vector.cpp b/paddle/capi/Vector.cpp new file mode 100644 index 0000000000..10dee7816c --- /dev/null +++ b/paddle/capi/Vector.cpp @@ -0,0 +1,26 @@ +#include "PaddleCAPI.h" +#include "PaddleCAPIPrivate.h" + +#define cast(v) paddle::capi::cast(v) +extern "C" { +int PDVecCreate(PD_Vector* vec, uint64_t size, bool useGpu) { + auto ptr = new paddle::capi::CVector(); + ptr->vec = paddle::Vector::create(size, useGpu); + *vec = ptr; + return PD_NO_ERROR; +} +int PDVecDestroy(PD_Vector vec) { + auto v = cast(vec); + v->vec.reset(); + delete v; + return PD_NO_ERROR; +} + +int PDVecIsSparse(PD_Vector vec, bool* isSparse) { + if (isSparse == nullptr || vec == nullptr) { + return PD_NULLPTR; + } + *isSparse = cast(vec)->vec->isSparse(); + return PD_NO_ERROR; +} +} diff --git a/paddle/capi/config.h.in b/paddle/capi/config.h.in new file mode 100644 index 0000000000..32d8a364e0 --- /dev/null +++ b/paddle/capi/config.h.in @@ -0,0 +1,6 @@ +#ifndef __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__ +#define __PADDLE_PADDLE_CAPI_CONFIG_H_INCLUDED__ + +typedef @PADDLE_FLOAT_TYPE@ pd_real; + +#endif diff --git a/paddle/capi/tests/CMakeLists.txt b/paddle/capi/tests/CMakeLists.txt new file mode 100644 index 0000000000..cd6b1d7c62 --- /dev/null +++ b/paddle/capi/tests/CMakeLists.txt @@ -0,0 +1,15 @@ +function(add_capi_unittest TARGET_NAME) + add_executable( + ${TARGET_NAME} + ${ARGN}) + target_link_libraries( + ${TARGET_NAME} + paddle_capi + paddle_test_main + ${GTEST_LIBRARIES}) + target_include_directories(${TARGET_NAME} PUBLIC ${PADDLE_CAPI_INC_PATH}) + add_test(NAME ${TARGET_NAME} COMMAND ${TARGET_NAME}) +endfunction() + +add_capi_unittest(capi_test_mats test_Vector.cpp + test_Matrix.cpp test_Arguments.cpp) diff --git a/paddle/capi/tests/test_Arguments.cpp b/paddle/capi/tests/test_Arguments.cpp new file mode 100644 index 0000000000..c74abd60d1 --- /dev/null +++ b/paddle/capi/tests/test_Arguments.cpp @@ -0,0 +1,54 @@ +#include "PaddleCAPI.h" +#include "gtest/gtest.h" +#include "paddle/utils/ThreadLocal.h" + +static std::vector randomBuffer(size_t bufSize) { + auto& eng = paddle::ThreadLocalRandomEngine::get(); + std::uniform_real_distribution dist(-1.0, 1.0); + std::vector retv; + retv.reserve(bufSize); + for (size_t i = 0; i < bufSize; ++i) { + retv.push_back(dist(eng)); + } + return retv; +} + +TEST(CAPIArguments, create) { + PD_Arguments args; + ASSERT_EQ(PD_NO_ERROR, PDArgsCreateNone(&args)); + uint64_t size; + ASSERT_EQ(PD_NO_ERROR, PDArgsGetSize(args, &size)); + ASSERT_EQ(0UL, size); + ASSERT_EQ(PD_NO_ERROR, PDArgsDestroy(args)); +} + +TEST(CAPIArguments, value) { + PD_Arguments args; + ASSERT_EQ(PD_NO_ERROR, PDArgsCreateNone(&args)); + ASSERT_EQ(PD_NO_ERROR, PDArgsResize(args, 1)); + + PD_Matrix mat; + ASSERT_EQ(PD_NO_ERROR, PDMatCreate(&mat, 128, 64, false)); + for (size_t i = 0; i < 128; ++i) { + std::vector sampleBuf = randomBuffer(64); + PDMatCopyToRow(mat, i, sampleBuf.data()); + } + ASSERT_EQ(PD_NO_ERROR, PDArgsSetValue(args, 0, mat)); + + PD_Matrix val; + ASSERT_EQ(PD_NO_ERROR, PDMatCreateNone(&val)); + + ASSERT_EQ(PD_NO_ERROR, PDArgsGetValue(args, 0, val)); + + for (size_t i = 0; i < 128; ++i) { + pd_real* row1; + pd_real* row2; + + ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(mat, i, &row1)); + ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(val, i, &row2)); + ASSERT_EQ(row1, row2); + } + ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(val)); + ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat)); + ASSERT_EQ(PD_NO_ERROR, PDArgsDestroy(args)); +} diff --git a/paddle/capi/tests/test_Matrix.cpp b/paddle/capi/tests/test_Matrix.cpp new file mode 100644 index 0000000000..0f04a46830 --- /dev/null +++ b/paddle/capi/tests/test_Matrix.cpp @@ -0,0 +1,33 @@ +#include "PaddleCAPI.h" +#include "gtest/gtest.h" + +TEST(CAPIMatrix, create) { + PD_Matrix mat; + ASSERT_EQ(PD_NO_ERROR, PDMatCreate(&mat, 128, 32, false)); + std::vector sampleRow; + sampleRow.resize(32); + for (size_t i = 0; i < sampleRow.size(); ++i) { + sampleRow[i] = 1.0 / (i + 1.0); + } + ASSERT_EQ(PD_NO_ERROR, PDMatCopyToRow(mat, 0, sampleRow.data())); + ASSERT_EQ(PD_OUT_OF_RANGE, PDMatCopyToRow(mat, 128, sampleRow.data())); + + pd_real* arrayPtr; + + ASSERT_EQ(PD_NO_ERROR, PDMatGetRow(mat, 0, &arrayPtr)); + for (size_t i = 0; i < sampleRow.size(); ++i) { + ASSERT_NEAR(sampleRow[i], arrayPtr[i], 1e-5); + } + + uint64_t height, width; + ASSERT_EQ(PD_NO_ERROR, PDMatGetShape(mat, &height, &width)); + ASSERT_EQ(128, height); + ASSERT_EQ(32, width); + ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat)); +} + +TEST(CAPIMatrix, createNone) { + PD_Matrix mat; + ASSERT_EQ(PD_NO_ERROR, PDMatCreateNone(&mat)); + ASSERT_EQ(PD_NO_ERROR, PDMatDestroy(mat)); +} diff --git a/paddle/capi/tests/test_Vector.cpp b/paddle/capi/tests/test_Vector.cpp new file mode 100644 index 0000000000..dbb987d440 --- /dev/null +++ b/paddle/capi/tests/test_Vector.cpp @@ -0,0 +1,11 @@ +#include "PaddleCAPI.h" +#include "gtest/gtest.h" + +TEST(CAPIVector, create) { + PD_Vector tmp; + ASSERT_EQ(PD_NO_ERROR, PDVecCreate(&tmp, 128, false)); + bool isSparse; + ASSERT_EQ(PD_NO_ERROR, PDVecIsSparse(tmp, &isSparse)); + ASSERT_FALSE(isSparse); + ASSERT_EQ(PD_NO_ERROR, PDVecDestroy(tmp)); +} diff --git a/paddle/utils/ForceLink.h b/paddle/utils/ForceLink.h new file mode 100644 index 0000000000..66005e2992 --- /dev/null +++ b/paddle/utils/ForceLink.h @@ -0,0 +1,46 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once + +/// Declare a force link file ID. It can be enabled by +/// `PADDLE_ENABLE_FORCE_LINK_FILE`. It is +/// +/// Example: +/// +/// In some_file.cpp +/// @code{cpp} +/// static paddle::InitFunction init([]{...}); +/// PADDLE_REGISTER_FORCE_LINK_FILE(some_file) +/// @endcode{cpp} +/// +/// In main.cpp +/// @code{cpp} +/// PADDLE_ENABLE_FORCE_LINK_FILE(some_file); +/// +/// int main() { +/// ... +/// } +/// @endcode{cpp} +/// +/// Then the InitFunction in some_file.cpp can be invoked. +#define PADDLE_REGISTER_FORCE_LINK_FILE(ID) \ + int __paddle_register_force_link_file_##ID##_method__() { return 0; } + +/// Enable a force link file. The file with ID's static variables could +/// be all initialized. +#define PADDLE_ENABLE_FORCE_LINK_FILE(ID) \ + extern int __paddle_register_force_link_file_##ID##_method__(); \ + static int __paddle_register_force_link_file_##ID##_handler__ = \ + __paddle_register_force_link_file_##ID##_method__(); diff --git a/paddle/utils/tests/CMakeLists.txt b/paddle/utils/tests/CMakeLists.txt index 26fafbd1ab..d9b018ebbb 100644 --- a/paddle/utils/tests/CMakeLists.txt +++ b/paddle/utils/tests/CMakeLists.txt @@ -15,3 +15,11 @@ if(NOT APPLE) COMMAND ${PROJ_ROOT}/paddle/utils/tests/test_CustomStackTracePrint.sh WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) endif() + +add_library(test_class_registrar_lib STATIC + test_ClassRegistrarLib.cpp + test_ClassRegistrarGlobals.cpp) + +add_simple_unittest(test_ClassRegistrar) +target_link_libraries(test_ClassRegistrar + test_class_registrar_lib) diff --git a/paddle/utils/tests/test_ClassRegistrar.cpp b/paddle/utils/tests/test_ClassRegistrar.cpp new file mode 100644 index 0000000000..c867045cb6 --- /dev/null +++ b/paddle/utils/tests/test_ClassRegistrar.cpp @@ -0,0 +1,27 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include +#include +#include "test_ClassRegistrarLib.h" +// Enable link test_ClassRegistrarLib.cpp +PADDLE_ENABLE_FORCE_LINK_FILE(test_registrar); + +TEST(ClassRegistrar, test) { + std::vector types; + gTestRegistrar_.forEachType( + [&types](const std::string& tp) { types.push_back(tp); }); + ASSERT_EQ(1, types.size()); + ASSERT_EQ("test", types[0]); +} diff --git a/paddle/utils/tests/test_ClassRegistrarGlobals.cpp b/paddle/utils/tests/test_ClassRegistrarGlobals.cpp new file mode 100644 index 0000000000..0f36da137f --- /dev/null +++ b/paddle/utils/tests/test_ClassRegistrarGlobals.cpp @@ -0,0 +1,16 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "test_ClassRegistrarLib.h" +paddle::ClassRegistrar gTestRegistrar_; diff --git a/paddle/utils/tests/test_ClassRegistrarLib.cpp b/paddle/utils/tests/test_ClassRegistrarLib.cpp new file mode 100644 index 0000000000..27071579f9 --- /dev/null +++ b/paddle/utils/tests/test_ClassRegistrarLib.cpp @@ -0,0 +1,31 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#include "test_ClassRegistrarLib.h" +#include +BaseClass::~BaseClass() {} + +class TestRegistrar : public BaseClass { +public: + TestRegistrar() {} + + virtual ~TestRegistrar() {} +}; + +static paddle::InitFunction init([] { + gTestRegistrar_.registerClass( + "test", []() -> BaseClass* { return new TestRegistrar(); }); +}); + +PADDLE_REGISTER_FORCE_LINK_FILE(test_registrar); diff --git a/paddle/utils/tests/test_ClassRegistrarLib.h b/paddle/utils/tests/test_ClassRegistrarLib.h new file mode 100644 index 0000000000..de2d02e70c --- /dev/null +++ b/paddle/utils/tests/test_ClassRegistrarLib.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserve. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. */ + +#pragma once +#include "paddle/utils/ClassRegistrar.h" + +class BaseClass { +public: + virtual ~BaseClass(); +}; + +extern paddle::ClassRegistrar gTestRegistrar_; -- GitLab