This is an automated email from the ASF dual-hosted git repository.

junrushao pushed a commit to branch 
revert-406-revert-395-2026-01-09/py-func-enhance
in repository https://gitbox.apache.org/repos/asf/tvm-ffi.git

commit b7a7d929911885404b77f6efbed6c34b5100ad49
Author: Junru Shao <[email protected]>
AuthorDate: Mon Jan 12 10:39:43 2026 -0800

    Revert "Revert "feat: Add `tvm_ffi.Function.__init__`" (#406)"
    
    This reverts commit 91fcaa8bd261d55255fe658ce026ce6840547234.
---
 include/tvm/ffi/base_details.h     |  1 -
 python/tvm_ffi/core.pyi            |  1 +
 python/tvm_ffi/cython/function.pxi | 21 +++++++++++++++++++++
 tests/python/test_function.py      |  9 +++++++++
 4 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/include/tvm/ffi/base_details.h b/include/tvm/ffi/base_details.h
index acbd652..ebaa5b4 100644
--- a/include/tvm/ffi/base_details.h
+++ b/include/tvm/ffi/base_details.h
@@ -86,7 +86,6 @@
 #else
 #define TVM_FFI_FUNC_SIG __func__
 #endif
-
 /// \endcond
 
 #if defined(TVM_FFI_DOXYGEN_MODE)
diff --git a/python/tvm_ffi/core.pyi b/python/tvm_ffi/core.pyi
index 2cee79c..1c3a3da 100644
--- a/python/tvm_ffi/core.pyi
+++ b/python/tvm_ffi/core.pyi
@@ -184,6 +184,7 @@ class DLTensorTestWrapper:
 def _dltensor_test_wrapper_c_dlpack_from_pyobject_as_intptr() -> int: ...
 
 class Function(Object):
+    def __init__(self, func: Callable[..., Any]) -> None: ...
     @property
     def release_gil(self) -> bool: ...
     @release_gil.setter
diff --git a/python/tvm_ffi/cython/function.pxi 
b/python/tvm_ffi/cython/function.pxi
index ec1542d..6a9638b 100644
--- a/python/tvm_ffi/cython/function.pxi
+++ b/python/tvm_ffi/cython/function.pxi
@@ -889,6 +889,27 @@ cdef class Function(Object):
     def __cinit__(self) -> None:
         self.c_release_gil = _RELEASE_GIL_BY_DEFAULT
 
+    def __init__(self, func: Callable[..., Any]) -> None:
+        """Initialize a Function from a Python callable.
+
+        This constructor allows creating a `tvm_ffi.Function` directly
+        from a Python function or another `tvm_ffi.Function` instance.
+
+        Parameters
+        ----------
+        func : Callable[..., Any]
+            The Python callable to wrap.
+        """
+        cdef TVMFFIObjectHandle chandle = NULL
+        if not callable(func):
+            raise TypeError(f"func must be callable, got {type(func)}")
+        if isinstance(func, Function):
+            chandle = (<Object>func).chandle
+            TVMFFIObjectIncRef(chandle)
+        else:
+            _convert_to_ffi_func_handle(func, &chandle)
+        self.chandle = chandle
+
     property release_gil:
         """Whether calls release the Python GIL while executing."""
 
diff --git a/tests/python/test_function.py b/tests/python/test_function.py
index 686fc08..de8aa7f 100644
--- a/tests/python/test_function.py
+++ b/tests/python/test_function.py
@@ -153,6 +153,15 @@ def test_pyfunc_convert() -> None:
     assert fapply(add, 1, 3.3) == 4.3
 
 
+def test_pyfunc_init() -> None:
+    def add(a: int, b: int) -> int:
+        return a + b
+
+    fadd = tvm_ffi.Function(add)
+    assert isinstance(fadd, tvm_ffi.Function)
+    assert fadd(1, 2) == 3
+
+
 def test_global_func() -> None:
     @tvm_ffi.register_global_func("mytest.echo")
     def echo(x: Any) -> Any:

Reply via email to