This is an automated email from the ASF dual-hosted git repository.
junrushao pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git
The following commit(s) were added to refs/heads/main by this push:
new 9186b44 [CPP] Introduce InvokeExternC (#117)
9186b44 is described below
commit 9186b44d63df3be9d3d67bb10b784f5e263f7e36
Author: Tianqi Chen <[email protected]>
AuthorDate: Tue Oct 14 12:15:35 2025 -0400
[CPP] Introduce InvokeExternC (#117)
This PR introduces a static method InvokeExternC to directly invoke an
already exported symbol in SafeCall convention without having to
construct an ffi::Function object
---
include/tvm/ffi/function.h | 38 ++++++++++++++++++++++++++++++++++++++
tests/cpp/test_function.cc | 6 ++++++
2 files changed, 44 insertions(+)
diff --git a/include/tvm/ffi/function.h b/include/tvm/ffi/function.h
index d665070..24155e3 100644
--- a/include/tvm/ffi/function.h
+++ b/include/tvm/ffi/function.h
@@ -512,6 +512,44 @@ class Function : public ObjectRef {
};
return FromPackedInternal(std::move(call_packed));
}
+
+ /*!
+ * \brief Directly invoke an extern "C" function that follows the TVM FFI
SafeCall convention.
+ *
+ * This function can be useful to turn an existing exported symbol into a
typed function.
+ *
+ * \code
+ *
+ * // An extern "C" function, matching TVMFFISafeCallType
+ * extern "C" int __tvm_ffi_add(
+ * void* handle, const TVMFFIAny* args, int32_t num_args, TVMFFIAny*result
+ * );
+ *
+ * // redirect an existing symbol into a typed function
+ * inline int add(int a, int b) {
+ * return tvm::ffi::Function::InvokeExternC(nullptr, __tvm_ffi_add, a,
b).cast<int>();
+ * }
+ *
+ * \endcode
+ *
+ * \tparam Args The types of the arguments to the extern function.
+ * \param handle The handle argument, for exported symbols this is usually
nullptr.
+ * \param safe_call The function pointer to the extern "C" function.
+ * \param args The arguments to pass to the function.
+ * \return The return value, wrapped in a tvm::ffi::Any.
+ */
+ template <typename... Args>
+ TVM_FFI_INLINE static Any InvokeExternC(void* handle, TVMFFISafeCallType
safe_call,
+ Args&&... args) {
+ const int kNumArgs = sizeof...(Args);
+ const int kArraySize = kNumArgs > 0 ? kNumArgs : 1;
+ AnyView args_pack[kArraySize];
+ PackedArgs::Fill(args_pack, std::forward<Args>(args)...);
+ Any result;
+ TVM_FFI_CHECK_SAFE_CALL(safe_call(handle, reinterpret_cast<const
TVMFFIAny*>(args_pack),
+ kNumArgs,
reinterpret_cast<TVMFFIAny*>(&result)));
+ return result;
+ }
/*!
* \brief Call function by directly passing in unpacked arguments.
*
diff --git a/tests/cpp/test_function.cc b/tests/cpp/test_function.cc
index f075f7f..b8ff769 100644
--- a/tests/cpp/test_function.cc
+++ b/tests/cpp/test_function.cc
@@ -263,4 +263,10 @@ TEST(Func, FromExternC) {
EXPECT_EQ(fadd1(1).cast<int>(), 2);
}
+int invoke_testing_add1(int x) {
+ return Function::InvokeExternC(nullptr, __tvm_ffi_testing_add1,
x).cast<int>();
+}
+
+TEST(Func, InvokeExternC) { EXPECT_EQ(invoke_testing_add1(1), 2); }
+
} // namespace