Introduction to
CLIF
左 遥(laike9m@)
左 遥(laike9m@)
CLIF provides a common foundation for creating C++ wrapper generators for various languages.
Lib | When to use |
---|---|
ctypes | call functions in shared libraries (DLL, .so) |
C-Extension | low level, replace the part you need |
Cython | A new language |
SWIG | wrap existing C/C++ libraries |
CLIF | wrap existing C++ libraries |
cpp_lib.h
void hello() {
std::cout << "hello world!";
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def hello()
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
cpp_lib.hello() # hello world!
cpp_lib.h
std::string return_hello() {
return "hello world!";
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def return_hello()
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.return_hello()) # None
cpp_lib.h
std::string return_hello() {
return "hello world!";
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def return_hello() -> str
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.return_hello()) # hello world!
cpp_lib.h
int add(int x, int y) {
return x + y;
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def add(x: int, y: int) -> int
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.add(1, 2)) # 3
default C++ type | CLIF type |
---|---|
int | int |
string | bytes or str |
bool | bool |
double | float |
vector<> | list<> |
pair<> | tuple<> |
unordered_set<> | set<> |
unordered_map<> | dict<> |
PyObject* | object |
int F(string input, string* output) {
*output = input;
return 0;
}
int F(input_param1, input_param2, ..., output_param1, output_param2) {
...
}
all input parameters before any output parameter(s)
- Google C++ convention
cpp_lib.h
int F(string input, string* output) {
*output = input;
return 0;
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def F(input: str) -> (code: int, output: str)
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.F('aaa')) # (0, 'aaa')
cpp_lib.h
string* F() {
static string s = "AAA";
std::cout << "s is: " << s;
return &s;
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def F() -> str
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.F()) # 'AAA'
cpp_lib.h
string& F() {
static string s = "AAA";
std::cout << "s is: " << s;
return s;
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
def F() -> str
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
s = cpp_lib.F() # s is: AAA
s = "BBB"
cpp_lib.F() # s is: AAA
cpp_lib.h
namespace foo {
std::string return_hello() {
return "hello world!";
}
}
cpp_lib.clif
from "experimental/users/yaoz/CLIF_test/cpp_lib.h":
namespace `foo`:
def return_hello() -> str
test.py
from google3.experimental.users.yaoz.CLIF_test.python import cpp_lib
print(cpp_lib.return_hello()) # hello world!
cpp_lib.clif
class MyClass:
def __init__(self, param: int, another_param: float)
def Method(self) -> dict<int, int>
@classmethod
def StaticMethod(cls, param: int)
# or better written as
staticmethods from `MyClass`:
def StaticMethod(param: int)
cpp_lib.h
class Foo {
public:
Foo(){};
Foo(int special) : var(special) {}
int var;
};
cpp_lib.clif
class Foo:
def __init__(self, special: int)
@add__init__
def Factory(self)
test.py
inst_a = cpp_lib.Foo(1)
inst_b = cpp_lib.Foo.Factory()
cpp_lib.h
class Vector {
public:
int Size();
};
cpp_lib.clif
class Vector:
def `Size` as __len__() -> int
cpp_lib.h
class A:
public:
v: list<int>
File get_file();
void set_file(File);
private:
File f;
cpp_lib.clif
class A:
v: list<int>
file: File = property(`get_file`, `set_file`)
cpp_lib.h
class Parent {
public:
void SomethingInteresting();
};
class Child : public Parent {
public:
void Useful();
};
cpp_lib.clif
class Child:
def SomethingInteresting(self)
def Useful(self)
cpp_lib.h
class Parent {
...
};
class Child : public Parent {
public:
void Useful();
};
cpp_lib.clif
from full.path.to.another.python.wrapper import Parent
from "c/include/path/to/child.h":
class Parent:
# wraps Parent class
class Child(Parent):
CLIF will release the GIL on every function call,
except for: