1
0
blueloveTH 2 жил өмнө
parent
commit
6dad2d612e
5 өөрчлөгдсөн 40 нэмэгдсэн , 3 устгасан
  1. 1 1
      build.sh
  2. 6 0
      docs/bindings.md
  3. 4 1
      include/typings/c.pyi
  4. 16 0
      src/cffi.cpp
  5. 13 1
      tests/80_c.py

+ 1 - 1
build.sh

@@ -14,7 +14,7 @@ if ! type -P clang++ >/dev/null 2>&1; then
     exit 1
 fi
 
-echo "Requirements satisfied: python3 and clang++ are installed."
+echo "Requirements satisfied: python3 and clang are installed."
 echo "It takes a moment to finish building."
 echo ""
 echo "> Running prebuild.py... "

+ 6 - 0
docs/bindings.md

@@ -227,6 +227,12 @@ struct Container{
 }
 ```
 
+For global objects, use the callback in `vm->heap`.
+```cpp
+void (*_gc_marker_ex)(VM*) = nullptr;
+```
+It will be invoked before a GC starts. So you can mark objects inside the callback to keep them alive.
+
 ### Others
 
 You may see somewhere in the code that `vm->bind_method<>` or `vm->bind_func<>` is used.

+ 4 - 1
include/typings/c.pyi

@@ -32,7 +32,10 @@ class Pointer(Generic[T], void_p):
     def __getitem__(self, index: int) -> T: ...
     def __setitem__(self, index: int, value: T) -> None: ...
 
-class char_p(Pointer[int]): pass
+class char_p(Pointer[int]):
+    def read_string(self) -> str: ...
+    def write_string(self, value: str) -> None: ...
+
 class uchar_p(Pointer[int]): pass
 class short_p(Pointer[int]): pass
 class ushort_p(Pointer[int]): pass

+ 16 - 0
src/cffi.cpp

@@ -226,6 +226,22 @@ void add_module_c(VM* vm){
     BIND_PRIMITIVE(bool, "bool")
 
 #undef BIND_PRIMITIVE
+
+    PyObject* char_p_t = mod->attr("char_p");
+    vm->bind(char_p_t, "read_string(self) -> str", [](VM* vm, ArgsView args){
+        VoidP& voidp = PK_OBJ_GET(VoidP, args[0]);
+        const char* target = (const char*)voidp.ptr;
+        return VAR(target);
+    });
+
+    vm->bind(char_p_t, "write_string(self, value: str)", [](VM* vm, ArgsView args){
+        VoidP& voidp = PK_OBJ_GET(VoidP, args[0]);
+        std::string_view sv = CAST(Str&, args[1]).sv();
+        char* target = (char*)voidp.ptr;
+        memcpy(target, sv.data(), sv.size());
+        target[sv.size()] = '\0';
+        return vm->None;
+    });
 }
 
 }   // namespace pkpy

+ 13 - 1
tests/80_c.py

@@ -49,4 +49,16 @@ class Vec2(c.struct):
 a = Vec2(1, 2)
 assert isinstance(a, c.struct)
 assert type(a) is Vec2
-assert repr(a) == "Vec2(1.0, 2.0)"
+assert repr(a) == "Vec2(1.0, 2.0)"
+
+a = c.struct(10)
+p = c.p_cast(a.addr(), c.char_p)
+p.write_string("Hello!")
+assert p[0] == ord("H")
+assert p[1] == ord("e")
+assert p[2] == ord("l")
+assert p[3] == ord("l")
+assert p[4] == ord("o")
+assert p[5] == ord("!")
+assert p[6] == 0
+assert p.read_string() == "Hello!"