|
|
@@ -0,0 +1,114 @@
|
|
|
+---
|
|
|
+icon: dot
|
|
|
+title: Precompiling
|
|
|
+---
|
|
|
+
|
|
|
+pkpy allows you to precompile your python code into a special form, which can be executed later.
|
|
|
+
|
|
|
+### In-memory precompilation
|
|
|
+
|
|
|
+You can use `vm->compile` to compile your source code into a `CodeObject_` object.
|
|
|
+This object can be executed later by `vm->_exec`.
|
|
|
+
|
|
|
+```cpp
|
|
|
+CodeObject_ code = vm->compile("print('Hello, world!')", "<string>", EXEC_MODE);
|
|
|
+vm->_exec(code); // Hello, world!
|
|
|
+```
|
|
|
+
|
|
|
+This `CodeObject_` object is a very non-generic form of the compiled code.
|
|
|
+It is an in-memory form. You are not able to save it to a file or load it from a file.
|
|
|
+
|
|
|
+
|
|
|
+### String precompilation
|
|
|
+
|
|
|
+In order to save the compiled code to a file, you need to use `vm->precompile`.
|
|
|
+It does some basic preprocessing and outputs the result as a human-readable string.
|
|
|
+
|
|
|
+```cpp
|
|
|
+// precompile the source code into a string
|
|
|
+Str source = vm->precompile("print('Hello, world!')", "<string>", EXEC_MODE);
|
|
|
+
|
|
|
+CodeObject code = vm->compile(source, "<string>", EXEC_MODE);
|
|
|
+vm->_exec(code); // Hello, world!
|
|
|
+```
|
|
|
+
|
|
|
+You can also use python's `compile` function to achieve the same effect.
|
|
|
+
|
|
|
+```python
|
|
|
+code = compile("print('Hello, world!')", "<string>", "exec")
|
|
|
+exec(code) # Hello, world!
|
|
|
+```
|
|
|
+
|
|
|
+Let's take a look at the precompiled string.
|
|
|
+```python
|
|
|
+print(code)
|
|
|
+```
|
|
|
+
|
|
|
+```txt
|
|
|
+pkpy:1.4.4
|
|
|
+0
|
|
|
+|print|
|
|
|
+=6
|
|
|
+5,1,0,
|
|
|
+6,1,5,1,0,
|
|
|
+42,1,1,
|
|
|
+8,1,1,S48656c6c6f2c20776f726c6421
|
|
|
+43,1,0,
|
|
|
+3,1,0,
|
|
|
+
|
|
|
+```
|
|
|
+
|
|
|
+Comparing with **In-memory precompilation**,
|
|
|
+**String precompilation** drops most of the original source code.
|
|
|
+It has an encryption effect, which can protect your source code from being stolen.
|
|
|
+It also means there is no source line information when an error occurs.
|
|
|
+
|
|
|
+```python
|
|
|
+src = """
|
|
|
+def f(a, b):
|
|
|
+ return g(a, b)
|
|
|
+
|
|
|
+def g(a, b):
|
|
|
+ c = f(a, b)
|
|
|
+ d = g(a, b)
|
|
|
+ return c + d
|
|
|
+"""
|
|
|
+
|
|
|
+code = compile(src, "<exec>", "exec")
|
|
|
+exec(code)
|
|
|
+f(1, 2)
|
|
|
+```
|
|
|
+
|
|
|
+You will get this (without source line information):
|
|
|
+```txt
|
|
|
+Traceback (most recent call last):
|
|
|
+ File "<exec>", line 3, in f
|
|
|
+ File "<exec>", line 6, in g
|
|
|
+ File "<exec>", line 3, in f
|
|
|
+ File "<exec>", line 6, in g
|
|
|
+ File "<exec>", line 3, in f
|
|
|
+ File "<exec>", line 6, in g
|
|
|
+ File "<exec>", line 3, in f
|
|
|
+StackOverflowError
|
|
|
+```
|
|
|
+
|
|
|
+instead of this (with source line information):
|
|
|
+
|
|
|
+```txt
|
|
|
+Traceback (most recent call last):
|
|
|
+ File "<stdin>", line 2, in f
|
|
|
+ return g(a, b)
|
|
|
+ File "<stdin>", line 2, in g
|
|
|
+ c = f(a, b)
|
|
|
+ File "<stdin>", line 2, in f
|
|
|
+ return g(a, b)
|
|
|
+ File "<stdin>", line 2, in g
|
|
|
+ c = f(a, b)
|
|
|
+ File "<stdin>", line 2, in f
|
|
|
+ return g(a, b)
|
|
|
+ File "<stdin>", line 2, in g
|
|
|
+ c = f(a, b)
|
|
|
+ File "<stdin>", line 2, in f
|
|
|
+ return g(a, b)
|
|
|
+StackOverflowError
|
|
|
+```
|