pythonc++bazel.socppyy

How to call function/classes in c++ .so files, generated by Bazel, in Python?


Let's say I have a simple class in hello.h

#ifndef LIB_HELLO_GREET_H_
#define LIB_HELLO_GREET_H_

class A{
public:
    int a = 0;
    int b = 0;
    int add(){
        return a+b;
    }
};

#endif

with bazel build file:

load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library")

cc_library(
    name = "hello",
    hdrs = ["hello.h"],
)

cc_binary(
    name = "hello.so",
    deps = [
        ":hello",
    ],
    linkshared=True,
    linkstatic=False
)

After I run bazel build hello.so, there is a shared object file generated in bazel-bin/main and bazel-bin/main/hello.so.runfiles/__main__/main/hello.so. Using those files, I want call class A with a python script. Ideally, I'd want to use cppyy or something similar.

I've tried with simple python scripts

import cppyy
cppyy.load_reflection_info('hello')
print(dir(cppyy.gbl))

or

import cppyy
cppyy.load_library('hello')
print(dir(cppyy.gbl))

with both .so files, but cppyy can't seem to detect class A - it is never inside cppyy.gbl

I'm wondering the best way to solve this problem, any help appreciated!


Solution

  • With cppyy, you also need to give it the header file, that is:

    cppyy.include("hello.h")
    

    and optionally use cppyy.add_include_path() to add the directory where hello.h resides, so that it can be found.

    An alternative is to use so-called "dictionaries." These package (customizable) directory locations, names of necessary headers files and (through linking) the shared library with the implementation into a single, new, shared library (named "dictionary" because of history). There can be a so-called "rootmap" file on the side that allows a class loader to find A automatically on first use. See the example in the documentation.