diff --git a/chore/llpyg/llpyg.go b/chore/llpyg/llpyg.go index b20b6f83..20630b11 100644 --- a/chore/llpyg/llpyg.go +++ b/chore/llpyg/llpyg.go @@ -59,6 +59,10 @@ func main() { json.Unmarshal(out.Bytes(), &mod) modName := mod.Name + if modName == "" { + log.Printf("import module %s failed\n", pyLib) + os.Exit(1) + } pkg := gogen.NewPackage("", modName, nil) pkg.Import("unsafe").MarkForceUsed(pkg) // import _ "unsafe" py := pkg.Import("github.com/goplus/llgo/py") // import "github.com/goplus/llgo/py" @@ -79,10 +83,11 @@ func main() { switch sym.Type { case "builtin_function_or_method", "function": ctx.genFunc(pkg, sym) - case "str", "float", "bool", "type", "dict", "list", "module", "int", "set": // skip + case "str", "float", "bool", "type", "dict", "tuple", "list", + "module", "int", "set", "frozenset", "flags": // skip default: t := sym.Type - if len(t) > 0 && (t[0] >= 'a' && t[0] <= 'z') { + if len(t) > 0 && (t[0] >= 'a' && t[0] <= 'z') && !strings.HasSuffix(t, "_info") { log.Panicln("unsupport type:", sym.Type) } } @@ -167,7 +172,7 @@ func genName(name string, idxDontTitle int) string { } name = strings.Join(parts, "") switch name { - case "default", "": + case "default", "func", "": name += "_" } return name diff --git a/py/_pyg/module.c b/py/_pyg/module.c index 7ce91821..571116d0 100644 --- a/py/_pyg/module.c +++ b/py/_pyg/module.c @@ -1,5 +1,6 @@ #include #include +#include // example: // llgoLoadPyModSyms(mod, "name1", &func1, "name2", &func2, NULL) @@ -23,3 +24,30 @@ void llgoLoadPyModSyms(PyObject* mod, ...) { } va_end(ap); } + +/* +wchar_t* toWcs(const char* str) { + size_t len = mbstowcs(NULL, str, 0); + wchar_t* wstr = (wchar_t*)malloc((len + 1) * sizeof(wchar_t)); + mbstowcs(wstr, str, len + 1); + return wstr; +} + +char* toMbs(const wchar_t* str) { + size_t len = wcstombs(NULL, str, 0); + char* mstr = (char*)malloc(len + 1); + wcstombs(mstr, str, len + 1); + return mstr; +} + +wchar_t *Py_GetPath(); + +void Py_SetPath(const wchar_t* path); +void Py_Initialize(); + +void llgoPyInitialize() { + setenv("PYTHONPATH", "/opt/homebrew/lib/python3.12/site-packages", 1); + Py_Initialize(); + printf("sys.path = %s\n", toMbs(Py_GetPath())); +} +*/ diff --git a/py/llgo_autogen.lla b/py/llgo_autogen.lla index 2d02e0b3..f8013ee2 100644 Binary files a/py/llgo_autogen.lla and b/py/llgo_autogen.lla differ diff --git a/py/object.go b/py/object.go index 923aa79f..56309d72 100644 --- a/py/object.go +++ b/py/object.go @@ -33,7 +33,7 @@ type Object struct { func (o *Object) DecRef() {} // llgo:link (*Object).Type C.PyObject_Type -func (o *Object) Type() *TypeObject { return nil } +func (o *Object) Type() *Object { return nil } // Compute a string representation of object o. Returns the string representation on // success, nil on failure. This is the equivalent of the Python expression str(o). @@ -45,13 +45,13 @@ func (o *Object) Str() *Object { return nil } // Returns 1 if the object o is considered to be true, and 0 otherwise. This is equivalent // to the Python expression not not o. On failure, return -1. // -// llgo:link (*Object) IsTrue() C.PyObject_IsTrue +// llgo:link (*Object).IsTrue C.PyObject_IsTrue func (o *Object) IsTrue() c.Int { return -1 } // Returns 0 if the object o is considered to be true, and 1 otherwise. This is equivalent // to the Python expression not o. On failure, return -1. // -// llgo:link (*Object) NotTrue() C.PyObject_Not +// llgo:link (*Object).NotTrue C.PyObject_Not func (o *Object) NotTrue() c.Int { return -1 } // ----------------------------------------------------------------------------- diff --git a/py/sys/gen.go b/py/sys/gen.go new file mode 100644 index 00000000..943c67a1 --- /dev/null +++ b/py/sys/gen.go @@ -0,0 +1,220 @@ +package sys + +import ( + _ "unsafe" + + "github.com/goplus/llgo/py" +) + +const LLGoPackage = "py.sys" + +// Adds a new audit hook callback. +// +//go:linkname Addaudithook py.addaudithook +func Addaudithook(hook *py.Object) *py.Object + +// Print an object to sys.stdout and also save it in builtins._ +// +//go:linkname Displayhook py.displayhook +func Displayhook(object *py.Object) *py.Object + +// Return the current exception. +// +// Return the most recent exception caught by an except clause +// in the current stack frame or in an older stack frame, or None +// if no such exception exists. +// +//go:linkname Exception py.exception +func Exception() *py.Object + +// Return current exception information: (type, value, traceback). +// +// Return information about the most recent exception caught by an except +// clause in the current stack frame or in an older stack frame. +// +//go:linkname ExcInfo py.exc_info +func ExcInfo() *py.Object + +// Handle an exception by displaying it with a traceback on sys.stderr. +// +//go:linkname Excepthook py.excepthook +func Excepthook(exctype *py.Object, value *py.Object, traceback *py.Object) *py.Object + +// Exit the interpreter by raising SystemExit(status). +// +// If the status is omitted or None, it defaults to zero (i.e., success). +// If the status is an integer, it will be used as the system exit status. +// If it is another kind of object, it will be printed and the system +// exit status will be one (i.e., failure). +// +//go:linkname Exit py.exit +func Exit(status *py.Object) *py.Object + +// Return the current default encoding used by the Unicode implementation. +// +//go:linkname Getdefaultencoding py.getdefaultencoding +func Getdefaultencoding() *py.Object + +// Return the current value of the flags that are used for dlopen calls. +// +// The flag constants are defined in the os module. +// +//go:linkname Getdlopenflags py.getdlopenflags +func Getdlopenflags() *py.Object + +// Return the number of memory blocks currently allocated. +// +//go:linkname Getallocatedblocks py.getallocatedblocks +func Getallocatedblocks() *py.Object + +// Return the number of elements of the unicode interned dictionary +// +//go:linkname Getunicodeinternedsize py.getunicodeinternedsize +func Getunicodeinternedsize() *py.Object + +// Return the encoding used to convert Unicode filenames to OS filenames. +// +//go:linkname Getfilesystemencoding py.getfilesystemencoding +func Getfilesystemencoding() *py.Object + +// Return the error mode used Unicode to OS filename conversion. +// +//go:linkname Getfilesystemencodeerrors py.getfilesystemencodeerrors +func Getfilesystemencodeerrors() *py.Object + +// Return the reference count of object. +// +// The count returned is generally one higher than you might expect, +// because it includes the (temporary) reference as an argument to +// getrefcount(). +// +//go:linkname Getrefcount py.getrefcount +func Getrefcount(object *py.Object) *py.Object + +// Return the current value of the recursion limit. +// +// The recursion limit is the maximum depth of the Python interpreter +// stack. This limit prevents infinite recursion from causing an overflow +// of the C stack and crashing Python. +// +//go:linkname Getrecursionlimit py.getrecursionlimit +func Getrecursionlimit() *py.Object + +// “Intern” the given string. +// +// This enters the string in the (global) table of interned strings whose +// purpose is to speed up dictionary lookups. Return the string itself or +// the previously interned string object with the same value. +// +//go:linkname Intern py.intern +func Intern(string *py.Object) *py.Object + +// Return True if Python is exiting. +// +//go:linkname IsFinalizing py.is_finalizing +func IsFinalizing() *py.Object + +// Set the ideal thread switching delay inside the Python interpreter. +// +// The actual frequency of switching threads can be lower if the +// interpreter executes long sequences of uninterruptible code +// (this is implementation-specific and workload-dependent). +// +// The parameter must represent the desired switching delay in seconds +// A typical value is 0.005 (5 milliseconds). +// +//go:linkname Setswitchinterval py.setswitchinterval +func Setswitchinterval(interval *py.Object) *py.Object + +// Return the current thread switch interval; see sys.setswitchinterval(). +// +//go:linkname Getswitchinterval py.getswitchinterval +func Getswitchinterval() *py.Object + +// Set the flags used by the interpreter for dlopen calls. +// +// This is used, for example, when the interpreter loads extension +// modules. Among other things, this will enable a lazy resolving of +// symbols when importing a module, if called as sys.setdlopenflags(0). +// To share symbols across extension modules, call as +// sys.setdlopenflags(os.RTLD_GLOBAL). Symbolic names for the flag +// modules can be found in the os module (RTLD_xxx constants, e.g. +// os.RTLD_LAZY). +// +//go:linkname Setdlopenflags py.setdlopenflags +func Setdlopenflags(flags *py.Object) *py.Object + +// Set the maximum depth of the Python interpreter stack to n. +// +// This limit prevents infinite recursion from causing an overflow of the C +// stack and crashing Python. The highest possible limit is platform- +// dependent. +// +//go:linkname Setrecursionlimit py.setrecursionlimit +func Setrecursionlimit(limit *py.Object) *py.Object + +// Return the global debug tracing function set with sys.settrace. +// +// See the debugger chapter in the library manual. +// +//go:linkname Gettrace py.gettrace +func Gettrace() *py.Object + +// Call func(*args), while tracing is enabled. +// +// The tracing state is saved, and restored afterwards. This is intended +// to be called from a debugger from a checkpoint, to recursively debug +// some other code. +// +//go:linkname CallTracing py.call_tracing +func CallTracing(func_ *py.Object, args *py.Object) *py.Object + +// Enable or disable origin tracking for coroutine objects in this thread. +// +// Coroutine objects will track 'depth' frames of traceback information +// about where they came from, available in their cr_origin attribute. +// +// Set a depth of 0 to disable. +// +//go:linkname SetCoroutineOriginTrackingDepth py.set_coroutine_origin_tracking_depth +func SetCoroutineOriginTrackingDepth(depth *py.Object) *py.Object + +// Check status of origin tracking for coroutine objects in this thread. +// +//go:linkname GetCoroutineOriginTrackingDepth py.get_coroutine_origin_tracking_depth +func GetCoroutineOriginTrackingDepth() *py.Object + +// Deactivate the current stack profiler trampoline backend. +// +// If no stack profiler is activated, this function has no effect. +// +//go:linkname DeactivateStackTrampoline py.deactivate_stack_trampoline +func DeactivateStackTrampoline() *py.Object + +// Return *True* if a stack profiler trampoline is active. +// +//go:linkname IsStackTrampolineActive py.is_stack_trampoline_active +func IsStackTrampolineActive() *py.Object + +// Handle an unraisable exception. +// +// The unraisable argument has the following attributes: +// +// * exc_type: Exception type. +// * exc_value: Exception value, can be None. +// * exc_traceback: Exception traceback, can be None. +// * err_msg: Error message, can be None. +// * object: Object causing the exception, can be None. +// +//go:linkname Unraisablehook py.unraisablehook +func Unraisablehook(unraisable *py.Object) *py.Object + +// Return the maximum string digits limit for non-binary int<->str conversions. +// +//go:linkname GetIntMaxStrDigits py.get_int_max_str_digits +func GetIntMaxStrDigits() *py.Object + +// Set the maximum string digits limit for non-binary int<->str conversions. +// +//go:linkname SetIntMaxStrDigits py.set_int_max_str_digits +func SetIntMaxStrDigits(maxdigits *py.Object) *py.Object diff --git a/py/type.go b/py/type.go index a78cb1c6..30b1fe54 100644 --- a/py/type.go +++ b/py/type.go @@ -22,20 +22,17 @@ import ( // https://docs.python.org/3/c-api/type.html -// TypeObject represents the Python type object. -type TypeObject = Object - // Return the type’s name. Equivalent to getting the type’s __name__ attribute. // -// llgo:link (*TypeObject).Name C.PyType_GetName -func (t *TypeObject) Name() *Object { return nil } +// llgo:link (*Object).TypeName C.PyType_GetName +func (t *Object) TypeName() *Object { return nil } // Return the tp_flags member of type. This function is primarily meant for use // with Py_LIMITED_API; the individual flag bits are guaranteed to be stable across // Python releases, but access to tp_flags itself is not part of the limited API. // -// llgo:link (*TypeObject).Flags C.PyType_GetFlags -func (t *TypeObject) Flags() uint32 { return 0 } +// llgo:link (*Object).TypeFlags C.PyType_GetFlags +func (t *Object) TypeFlags() uint32 { return 0 } // Return the module object associated with the given type when the type was created // using PyType_FromModuleAndSpec(). @@ -49,8 +46,8 @@ func (t *TypeObject) Flags() uint32 { return 0 } // the class that defines the method. See ModuleByDef() for cases when PyCMethod // cannot be used. // -// llgo:link (*TypeObject).Module C.PyType_GetModule -func (t *TypeObject) Module() *Object { return nil } +// llgo:link (*Object).TypeModule C.PyType_GetModule +func (t *Object) TypeModule() *Object { return nil } -// llgo:link (*TypeObject).ModuleByDef C.PyType_GetModuleByDef -// func (t *TypeObject) ModuleByDef(def *ModuleDef) *Object { return nil } +// llgo:link (*Object).TypeModuleByDef C.PyType_GetModuleByDef +// func (t *Object) TypeModuleByDef(def *ModuleDef) *Object { return nil }