-
Notifications
You must be signed in to change notification settings - Fork 39
Add CppInterOp API dispatch mechanism #730
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
b8e6c08
0ab686d
4cd8f9a
2ce71ec
a768abb
ca9add1
191eb4e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,298 @@ | ||||||||||
| //--------------------------------------------------------------------*- C++ -*- | ||||||||||
| // CppInterOp Dispatch Mechanism | ||||||||||
| // author: Aaron Jomy <[email protected]> | ||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||
| // | ||||||||||
| // This defines the mechanism which enables dispatching of the CppInterOp API | ||||||||||
| // without linking to it, preventing any LLVM or Clang symbols from being leaked | ||||||||||
| // into the client application. | ||||||||||
| // | ||||||||||
| //===----------------------------------------------------------------------===// | ||||||||||
| #ifndef CPPINTEROP_CPPINTEROPDISPATCH_H | ||||||||||
| #define CPPINTEROP_CPPINTEROPDISPATCH_H | ||||||||||
|
|
||||||||||
| #include <cstddef> | ||||||||||
| #include <cstdint> | ||||||||||
| #include <set> | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: included header cstdint is not used directly [misc-include-cleaner]
Suggested change
|
||||||||||
| #include <string> | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: included header set is not used directly [misc-include-cleaner]
Suggested change
|
||||||||||
| #include <vector> | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: included header string is not used directly [misc-include-cleaner]
Suggested change
|
||||||||||
|
|
||||||||||
aaronj0 marked this conversation as resolved.
Show resolved
Hide resolved
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: included header vector is not used directly [misc-include-cleaner]
Suggested change
|
||||||||||
| #include <cstdlib> | ||||||||||
| #include <dlfcn.h> | ||||||||||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. needs something like: #ifdef _WIN32
#include <io.h>
#include <Psapi.h>
#define RTLD_DEFAULT ((void *)::GetModuleHandle(NULL))
//#define dlsym(library, function_name) ::GetProcAddress((HMODULE)library, function_name)
#define dlopen(library_name, flags) ::LoadLibrary(library_name)
#define dlclose(library) ::FreeLibrary((HMODULE)library)
#endif |
||||||||||
| #include <iostream> | ||||||||||
| #include <mutex> | ||||||||||
|
|
||||||||||
| #include <CppInterOp/CppInterOp.h> | ||||||||||
|
|
||||||||||
| // Configured by CMake, can be overridden by defining before including this | ||||||||||
| // header | ||||||||||
| #ifndef CPPINTEROP_LIBRARY_PATH | ||||||||||
| #define CPPINTEROP_LIBRARY_PATH "@CPPINTEROP_LIBRARY_PATH@" | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That does not seem correct. The library can be installed or relocated.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not the build location, but a new flag. The path can be overridden to the installed/relocated location either with CMake or by setting an env var. The header has no way of knowing that...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is still a problem, however, I do not understand why you need to define it if it is provided from the outside... |
||||||||||
| #endif | ||||||||||
|
|
||||||||||
| using __CPP_FUNC = void (*)(); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: declaration uses identifier '__CPP_FUNC', which is a reserved identifier [bugprone-reserved-identifier]
Suggested change
include/CppInterOp/CppInterOpDispatch.h:24: - __CPP_FUNC address;
+ CPP_FUNC address;
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: declaration uses identifier '__CPP_FUNC', which is a reserved identifier [bugprone-reserved-identifier]
Suggested change
|
||||||||||
|
|
||||||||||
| ///\param[in] procname - the name of the FunctionEntry in the symbol lookup | ||||||||||
| /// table. | ||||||||||
| /// | ||||||||||
| ///\returns the function address of the requested API, or nullptr if not found | ||||||||||
| extern "C" CPPINTEROP_API void ( | ||||||||||
| *CppGetProcAddress(const unsigned char* procname))(void); | ||||||||||
|
|
||||||||||
| #define EXTERN_CPP_FUNC_SIMPLE(func_name) \ | ||||||||||
| extern CppAPIType::func_name func_name; | ||||||||||
|
|
||||||||||
| #define EXTERN_CPP_FUNC_OVERLOADED(func_name, signature) \ | ||||||||||
| extern CppAPIType::func_name func_name; | ||||||||||
|
|
||||||||||
| #define LOAD_CPP_FUNCTION_SIMPLE(func_name) \ | ||||||||||
| func_name = \ | ||||||||||
| reinterpret_cast<CppAPIType::func_name>(dlGetProcAddress(#func_name)); | ||||||||||
|
|
||||||||||
| #define LOAD_CPP_FUNCTION_OVERLOADED(func_name, signature) \ | ||||||||||
| func_name = \ | ||||||||||
| reinterpret_cast<CppAPIType::func_name>(dlGetProcAddress(#func_name)); | ||||||||||
|
|
||||||||||
| #define DECLARE_CPP_NULL_SIMPLE(func_name) \ | ||||||||||
| CppAPIType::func_name func_name = nullptr; | ||||||||||
|
|
||||||||||
| #define DECLARE_CPP_NULL_OVERLOADED(func_name, signature) \ | ||||||||||
| CppAPIType::func_name func_name = nullptr; | ||||||||||
|
|
||||||||||
| // macro that allows declaration and loading of all CppInterOp API functions in | ||||||||||
| // a consistent way. This is used as our dispatched API list, along with the | ||||||||||
| // name-address pair table | ||||||||||
| #define FOR_EACH_CPP_FUNCTION_SIMPLE(DO) \ | ||||||||||
| DO(CreateInterpreter) \ | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This can take a pair <
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ping on this. We want to be writing the using clauses automatically.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this is indeed possible. #define EXTERN_CPP_FUNC_SIMPLE(func_name) \
extern CppAPIType::func_name func_name;
#define EXTERN_CPP_FUNC_OVERLOADED(func_name, signature) \
extern CppAPIType::func_name func_name;
#define LOAD_CPP_FUNCTION_SIMPLE(func_name) \
func_name = reinterpret_cast<CppAPIType::func_name>(dlGetProcAddress(#func_name));
#define LOAD_CPP_FUNCTION_OVERLOADED(func_name, signature) \
func_name = reinterpret_cast<CppAPIType::func_name>(dlGetProcAddress(#func_name));
#define DECLARE_CPP_NULL_SIMPLE(func_name) \
CppAPIType::func_name func_name = nullptr;
#define DECLARE_CPP_NULL_OVERLOADED(func_name, signature) \
CppAPIType::func_name func_name = nullptr;
// macro that allows declaration and loading of all CppInterOp API functions in
// a consistent way. This is used as our dispatched API list, along with the
// name-address pair table
#define FOR_EACH_CPP_FUNCTION_SIMPLE(DO) \
DO(CreateInterpreter) \
DO(GetInterpreter) \
// ... rest of non overloaded API
DO(EnableDebugOutput)
#define FOR_EACH_CPP_FUNCTION_OVERLOADED(DO) \
DO(MakeFunctionCallable, Cpp::JitCall (*)(Cpp::TCppConstFunction_t)) \
DO(GetFunctionAddress, Cpp::TCppFuncAddr_t (*)(Cpp::TCppFunction_t))
#define EXTRACT_NAME_OVERLOADED(name, sig) name
#define FOR_EACH_CPP_FUNCTION(DO) \
FOR_EACH_CPP_FUNCTION_SIMPLE(DO) \
FOR_EACH_CPP_FUNCTION_OVERLOADED(EXTRACT_NAME_OVERLOADED)
#define DECLARE_TYPE_SIMPLE(func_name) \
using func_name = decltype(&Cpp::func_name);
#define DECLARE_TYPE_OVERLOADED(func_name, signature) \
using func_name = signature;
namespace CppDispatch {
// Forward all type aliases
using TCppIndex_t = ::Cpp::TCppIndex_t;
...
using JitCall = ::Cpp::JitCall;
} // end namespace CppDispatch
namespace CppAPIType {
FOR_EACH_CPP_FUNCTION_SIMPLE(DECLARE_TYPE_SIMPLE)
FOR_EACH_CPP_FUNCTION_OVERLOADED(DECLARE_TYPE_OVERLOADED)
} // end namespace CppAPIType
#undef DECLARE_TYPE_SIMPLE
#undef DECLARE_TYPE_OVERLOADED
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Of course all usages of the previous macro split up: - FOR_EACH_CPP_FUNCTION(LOAD_CPP_FUNCTION)
+ FOR_EACH_CPP_FUNCTION_SIMPLE(LOAD_CPP_FUNCTION_SIMPLE)
+ FOR_EACH_CPP_FUNCTION_OVERLOADED(LOAD_CPP_FUNCTION_OVERLOADED)
- FOR_EACH_CPP_FUNCTION(EXTERN_CPP_FUNC)
+ FOR_EACH_CPP_FUNCTION_SIMPLE(EXTERN_CPP_FUNC_SIMPLE)
+ FOR_EACH_CPP_FUNCTION_OVERLOADED(EXTERN_CPP_FUNC_OVERLOADED)But that keeps the whole thing automatic
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably you don't need such a complexity but a X-macro that expands. You can also take the type of the function using
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Can you give me a clearer idea on that?
Well, yes I can make this simpler if I write the signatures for all API and take the decltype of the function obtained on static_cast. I've split up the macros to avoid static_cast on non-overloaded methods, as that seems like an unnecessary operation...
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||||||||||
| DO(GetInterpreter) \ | ||||||||||
| DO(Process) \ | ||||||||||
| DO(GetResourceDir) \ | ||||||||||
| DO(AddIncludePath) \ | ||||||||||
| DO(LoadLibrary) \ | ||||||||||
| DO(Declare) \ | ||||||||||
| DO(DeleteInterpreter) \ | ||||||||||
| DO(IsNamespace) \ | ||||||||||
| DO(ObjToString) \ | ||||||||||
| DO(GetQualifiedCompleteName) \ | ||||||||||
| DO(GetValueKind) \ | ||||||||||
| DO(GetNonReferenceType) \ | ||||||||||
| DO(IsEnumType) \ | ||||||||||
| DO(GetIntegerTypeFromEnumType) \ | ||||||||||
| DO(GetReferencedType) \ | ||||||||||
| DO(IsPointerType) \ | ||||||||||
| DO(GetPointeeType) \ | ||||||||||
| DO(GetPointerType) \ | ||||||||||
| DO(IsReferenceType) \ | ||||||||||
| DO(GetTypeAsString) \ | ||||||||||
| DO(GetCanonicalType) \ | ||||||||||
| DO(HasTypeQualifier) \ | ||||||||||
| DO(RemoveTypeQualifier) \ | ||||||||||
| DO(GetUnderlyingType) \ | ||||||||||
| DO(IsRecordType) \ | ||||||||||
| DO(IsFunctionPointerType) \ | ||||||||||
| DO(GetVariableType) \ | ||||||||||
| DO(GetNamed) \ | ||||||||||
| DO(GetScopeFromType) \ | ||||||||||
| DO(GetClassTemplateInstantiationArgs) \ | ||||||||||
| DO(IsClass) \ | ||||||||||
| DO(GetType) \ | ||||||||||
| DO(GetTypeFromScope) \ | ||||||||||
| DO(GetComplexType) \ | ||||||||||
| DO(GetIntegerTypeFromEnumScope) \ | ||||||||||
| DO(GetUnderlyingScope) \ | ||||||||||
| DO(GetScope) \ | ||||||||||
| DO(GetGlobalScope) \ | ||||||||||
| DO(GetScopeFromCompleteName) \ | ||||||||||
| DO(InstantiateTemplate) \ | ||||||||||
| DO(GetParentScope) \ | ||||||||||
| DO(IsTemplate) \ | ||||||||||
| DO(IsTemplateSpecialization) \ | ||||||||||
| DO(IsTypedefed) \ | ||||||||||
| DO(IsClassPolymorphic) \ | ||||||||||
| DO(Demangle) \ | ||||||||||
| DO(SizeOf) \ | ||||||||||
| DO(GetSizeOfType) \ | ||||||||||
| DO(IsBuiltin) \ | ||||||||||
| DO(IsComplete) \ | ||||||||||
| DO(Allocate) \ | ||||||||||
| DO(Deallocate) \ | ||||||||||
| DO(Construct) \ | ||||||||||
| DO(Destruct) \ | ||||||||||
| DO(IsAbstract) \ | ||||||||||
| DO(IsEnumScope) \ | ||||||||||
| DO(IsEnumConstant) \ | ||||||||||
| DO(IsAggregate) \ | ||||||||||
| DO(HasDefaultConstructor) \ | ||||||||||
| DO(IsVariable) \ | ||||||||||
| DO(GetAllCppNames) \ | ||||||||||
| DO(GetUsingNamespaces) \ | ||||||||||
| DO(GetCompleteName) \ | ||||||||||
| DO(GetDestructor) \ | ||||||||||
| DO(IsVirtualMethod) \ | ||||||||||
| DO(GetNumBases) \ | ||||||||||
| DO(GetName) \ | ||||||||||
| DO(GetBaseClass) \ | ||||||||||
| DO(IsSubclass) \ | ||||||||||
| DO(GetOperator) \ | ||||||||||
| DO(GetFunctionReturnType) \ | ||||||||||
| DO(GetBaseClassOffset) \ | ||||||||||
| DO(GetClassMethods) \ | ||||||||||
| DO(GetFunctionsUsingName) \ | ||||||||||
| DO(GetFunctionNumArgs) \ | ||||||||||
| DO(GetFunctionRequiredArgs) \ | ||||||||||
| DO(GetFunctionArgName) \ | ||||||||||
| DO(GetFunctionArgType) \ | ||||||||||
| DO(GetFunctionArgDefault) \ | ||||||||||
| DO(IsConstMethod) \ | ||||||||||
| DO(GetFunctionTemplatedDecls) \ | ||||||||||
| DO(ExistsFunctionTemplate) \ | ||||||||||
| DO(IsTemplatedFunction) \ | ||||||||||
| DO(IsStaticMethod) \ | ||||||||||
| DO(GetClassTemplatedMethods) \ | ||||||||||
| DO(BestOverloadFunctionMatch) \ | ||||||||||
| DO(GetOperatorFromSpelling) \ | ||||||||||
| DO(IsFunctionDeleted) \ | ||||||||||
| DO(IsPublicMethod) \ | ||||||||||
| DO(IsProtectedMethod) \ | ||||||||||
| DO(IsPrivateMethod) \ | ||||||||||
| DO(IsConstructor) \ | ||||||||||
| DO(IsDestructor) \ | ||||||||||
| DO(GetDatamembers) \ | ||||||||||
| DO(GetStaticDatamembers) \ | ||||||||||
| DO(GetEnumConstantDatamembers) \ | ||||||||||
| DO(LookupDatamember) \ | ||||||||||
| DO(IsLambdaClass) \ | ||||||||||
| DO(GetQualifiedName) \ | ||||||||||
| DO(GetVariableOffset) \ | ||||||||||
| DO(IsPublicVariable) \ | ||||||||||
| DO(IsProtectedVariable) \ | ||||||||||
| DO(IsPrivateVariable) \ | ||||||||||
| DO(IsStaticVariable) \ | ||||||||||
| DO(IsConstVariable) \ | ||||||||||
| DO(GetDimensions) \ | ||||||||||
| DO(GetEnumConstants) \ | ||||||||||
| DO(GetEnumConstantType) \ | ||||||||||
| DO(GetEnumConstantValue) \ | ||||||||||
| DO(DumpScope) \ | ||||||||||
| DO(AddSearchPath) \ | ||||||||||
| DO(Evaluate) \ | ||||||||||
| DO(IsDebugOutputEnabled) \ | ||||||||||
| DO(EnableDebugOutput) | ||||||||||
|
|
||||||||||
| #define FOR_EACH_CPP_FUNCTION_OVERLOADED(DO) \ | ||||||||||
| DO(MakeFunctionCallable, Cpp::JitCall (*)(Cpp::TCppConstFunction_t)) \ | ||||||||||
| DO(GetFunctionAddress, Cpp::TCppFuncAddr_t (*)(Cpp::TCppFunction_t)) | ||||||||||
|
|
||||||||||
| #define EXTRACT_NAME_OVERLOADED(name, sig) name | ||||||||||
|
|
||||||||||
| #define FOR_EACH_CPP_FUNCTION(DO) \ | ||||||||||
| FOR_EACH_CPP_FUNCTION_SIMPLE(DO) \ | ||||||||||
| FOR_EACH_CPP_FUNCTION_OVERLOADED(EXTRACT_NAME_OVERLOADED) | ||||||||||
|
|
||||||||||
| #define DECLARE_TYPE_SIMPLE(func_name) \ | ||||||||||
| using func_name = decltype(&Cpp::func_name); | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
Suggested change
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These are good suggestions.. |
||||||||||
|
|
||||||||||
| #define DECLARE_TYPE_OVERLOADED(func_name, signature) \ | ||||||||||
| using func_name = signature; | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: macro argument should be enclosed in parentheses [bugprone-macro-parentheses]
Suggested change
|
||||||||||
| namespace CppDispatch { | ||||||||||
| // Forward all type aliases | ||||||||||
| using TCppIndex_t = ::Cpp::TCppIndex_t; | ||||||||||
| using TCppScope_t = ::Cpp::TCppScope_t; | ||||||||||
| using TCppConstScope_t = ::Cpp::TCppConstScope_t; | ||||||||||
| using TCppType_t = ::Cpp::TCppType_t; | ||||||||||
| using TCppFunction_t = ::Cpp::TCppFunction_t; | ||||||||||
| using TCppConstFunction_t = ::Cpp::TCppConstFunction_t; | ||||||||||
| using TCppFuncAddr_t = ::Cpp::TCppFuncAddr_t; | ||||||||||
| using TInterp_t = ::Cpp::TInterp_t; | ||||||||||
| using TCppObject_t = ::Cpp::TCppObject_t; | ||||||||||
|
|
||||||||||
| using Operator = ::Cpp::Operator; | ||||||||||
| using OperatorArity = ::Cpp::OperatorArity; | ||||||||||
| using QualKind = ::Cpp::QualKind; | ||||||||||
| using TemplateArgInfo = ::Cpp::TemplateArgInfo; | ||||||||||
| using ValueKind = ::Cpp::ValueKind; | ||||||||||
|
|
||||||||||
| using JitCall = ::Cpp::JitCall; | ||||||||||
| } // end namespace CppDispatch | ||||||||||
|
|
||||||||||
| namespace CppAPIType { | ||||||||||
| FOR_EACH_CPP_FUNCTION_SIMPLE(DECLARE_TYPE_SIMPLE) | ||||||||||
| FOR_EACH_CPP_FUNCTION_OVERLOADED(DECLARE_TYPE_OVERLOADED) | ||||||||||
| } // end namespace CppAPIType | ||||||||||
|
|
||||||||||
| #undef DECLARE_TYPE_SIMPLE | ||||||||||
| #undef DECLARE_TYPE_OVERLOADED | ||||||||||
|
|
||||||||||
| // TODO: implement overload that takes an existing opened DL handle | ||||||||||
| inline void* dlGetProcAddress(const char* name, | ||||||||||
| const char* customLibPath = nullptr) { | ||||||||||
| if (!name) | ||||||||||
| return nullptr; | ||||||||||
|
|
||||||||||
| static std::once_flag loaded; | ||||||||||
| static void* handle = nullptr; | ||||||||||
| static void* (*getCppProcAddress)(const char*) = nullptr; | ||||||||||
|
|
||||||||||
| std::call_once(loaded, [customLibPath]() { | ||||||||||
| // priority order: 1) custom path argument, or CPPINTEROP_LIBRARY_PATH via | ||||||||||
| // 2) cmake configured path 3) env vars | ||||||||||
| const char* libPath = customLibPath; | ||||||||||
| if (!libPath) { | ||||||||||
| libPath = std::getenv("CPPINTEROP_LIBRARY_PATH"); | ||||||||||
| } | ||||||||||
| if (!libPath || libPath[0] == '\0') { | ||||||||||
| libPath = CPPINTEROP_LIBRARY_PATH; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| handle = dlopen(libPath, RTLD_LOCAL | RTLD_NOW); | ||||||||||
| if (!handle) { | ||||||||||
| std::cerr << "[CppInterOp] Failed to load library from " << libPath | ||||||||||
| << ": " << dlerror() << '\n'; | ||||||||||
| return; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| getCppProcAddress = reinterpret_cast<void* (*)(const char*)>( | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: do not use reinterpret_cast [cppcoreguidelines-pro-type-reinterpret-cast] getCppProcAddress = reinterpret_cast<void* (*)(const char*)>(
^
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
| dlsym(handle, "CppGetProcAddress")); | ||||||||||
| if (!getCppProcAddress) { | ||||||||||
| std::cerr << "[CppInterOp] Failed to find CppGetProcAddress: " | ||||||||||
| << dlerror() << '\n'; | ||||||||||
| dlclose(handle); | ||||||||||
| handle = nullptr; | ||||||||||
| } | ||||||||||
| }); | ||||||||||
|
|
||||||||||
| return getCppProcAddress ? getCppProcAddress(name) : nullptr; | ||||||||||
| } | ||||||||||
| namespace CppDispatch { | ||||||||||
| FOR_EACH_CPP_FUNCTION_SIMPLE(EXTERN_CPP_FUNC_SIMPLE) | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'AddIncludePath' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] FOR_EACH_CPP_FUNCTION_SIMPLE(EXTERN_CPP_FUNC_SIMPLE)
^Additional contextinclude/CppInterOp/CppInterOpDispatch.h:69: expanded from macro 'FOR_EACH_CPP_FUNCTION_SIMPLE' DO(AddIncludePath) \
^
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'AddSearchPath' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] FOR_EACH_CPP_FUNCTION_SIMPLE(EXTERN_CPP_FUNC_SIMPLE)
^Additional contextinclude/CppInterOp/CppInterOpDispatch.h:176: expanded from macro 'FOR_EACH_CPP_FUNCTION_SIMPLE' DO(AddSearchPath) \
^
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. warning: variable 'Allocate' is non-const and globally accessible, consider making it const [cppcoreguidelines-avoid-non-const-global-variables] FOR_EACH_CPP_FUNCTION_SIMPLE(EXTERN_CPP_FUNC_SIMPLE)
^Additional contextinclude/CppInterOp/CppInterOpDispatch.h:116: expanded from macro 'FOR_EACH_CPP_FUNCTION_SIMPLE' DO(Allocate) \
^ |
||||||||||
| FOR_EACH_CPP_FUNCTION_OVERLOADED(EXTERN_CPP_FUNC_OVERLOADED) | ||||||||||
|
|
||||||||||
| /// Initialize all CppInterOp API from the dynamically loaded library | ||||||||||
| /// (RTLD_LOCAL) \param[in] customLibPath Optional custom path to | ||||||||||
| /// libclangCppInterOp.so \returns true if initialization succeeded, false | ||||||||||
| /// otherwise | ||||||||||
| inline bool init_functions(const char* customLibPath = nullptr) { | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That should be a test case, right? |
||||||||||
| // trigger library loading if custom path provided | ||||||||||
| if (customLibPath) { | ||||||||||
| void* test = dlGetProcAddress("GetInterpreter", customLibPath); | ||||||||||
| if (!test) { | ||||||||||
| std::cerr << "[CppInterOp] Failed to initialize with custom path: " | ||||||||||
| << customLibPath << '\n'; | ||||||||||
| return false; | ||||||||||
| } | ||||||||||
| } | ||||||||||
|
|
||||||||||
| FOR_EACH_CPP_FUNCTION_SIMPLE(LOAD_CPP_FUNCTION_SIMPLE) | ||||||||||
| FOR_EACH_CPP_FUNCTION_OVERLOADED(LOAD_CPP_FUNCTION_OVERLOADED) | ||||||||||
|
|
||||||||||
| // test to verify that critical (and consequently all) functions loaded | ||||||||||
| if (!GetInterpreter || !CreateInterpreter) { | ||||||||||
| std::cerr << "[CppInterOp] Failed to load critical functions" << std::endl; | ||||||||||
| return false; | ||||||||||
| } | ||||||||||
|
|
||||||||||
| return true; | ||||||||||
| } | ||||||||||
| } // namespace CppDispatch | ||||||||||
|
|
||||||||||
| #endif // CPPINTEROP_CPPINTEROPDISPATCH_H | ||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -109,6 +109,7 @@ endif() | |
| add_llvm_library(clangCppInterOp | ||
| DISABLE_LLVM_LINK_LLVM_DYLIB | ||
| CppInterOp.cpp | ||
| CppInterOpDispatch.cpp | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should name the infrastructure we built with something closer to what it does, eg.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ping.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| CXCppInterOp.cpp | ||
| ${DLM} | ||
| LINK_LIBS | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| //------------------------------------------------------------------------------ | ||
| // CppInterOp Dispatch Implementation | ||
| // author: Aaron Jomy <[email protected]> | ||
| //------------------------------------------------------------------------------ | ||
|
|
||
| #include <CppInterOp/CppInterOp.h> | ||
| #include <CppInterOp/CppInterOpDispatch.h> | ||
|
|
||
| #include <unordered_map> | ||
|
|
||
| // Macro for simple functions (direct cast) | ||
| #define MAP_ENTRY_SIMPLE(func_name) {#func_name, (__CPP_FUNC)Cpp::func_name}, | ||
|
|
||
| // Macro for overloaded functions (needs static_cast with signature) | ||
| #define MAP_ENTRY_OVERLOADED(func_name, signature) \ | ||
| {#func_name, (__CPP_FUNC) static_cast<signature>(&Cpp::func_name)}, | ||
|
|
||
| static const std::unordered_map<std::string_view, __CPP_FUNC> | ||
| INTEROP_FUNCTIONS = { | ||
| FOR_EACH_CPP_FUNCTION_SIMPLE(MAP_ENTRY_SIMPLE) | ||
| FOR_EACH_CPP_FUNCTION_OVERLOADED(MAP_ENTRY_OVERLOADED)}; | ||
|
|
||
| #undef MAP_ENTRY_SIMPLE | ||
| #undef MAP_ENTRY_OVERLOADED | ||
|
|
||
| static inline __CPP_FUNC _cppinterop_get_proc_address(const char* funcName) { | ||
| auto it = INTEROP_FUNCTIONS.find(funcName); | ||
| return (it != INTEROP_FUNCTIONS.end()) ? it->second : nullptr; | ||
| } | ||
|
|
||
| void (*CppGetProcAddress(const unsigned char* procName))(void) { | ||
| return _cppinterop_get_proc_address(reinterpret_cast<const char*>(procName)); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -11,6 +11,14 @@ else() | |
| set(EXTRA_PATH_TEST_BINARIES /CppInterOpTests/unittests/bin/$<CONFIG>/) | ||
| endif() | ||
|
|
||
| # Add the DispatchAPITest only when building shared libraries | ||
| if (BUILD_SHARED_LIBS) | ||
| set_source_files_properties(DispatchAPITest.cpp PROPERTIES COMPILE_DEFINITIONS | ||
| "CPPINTEROP_LIB_DIR=\"${CMAKE_BINARY_DIR}/lib/libclangCppInterOp${CMAKE_SHARED_LIBRARY_SUFFIX}\"" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please write a test and try to run that test against installed CppInterOp with the build folder deleted. |
||
| ) | ||
| list(APPEND EXTRA_TEST_SOURCE_FILES DispatchAPITest.cpp) | ||
| endif() | ||
|
|
||
| add_cppinterop_unittest(CppInterOpTests | ||
| EnumReflectionTest.cpp | ||
| FunctionReflectionTest.cpp | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warning: included header cstddef is not used directly [misc-include-cleaner]