-
Hi there! I want to create a python binding for LLVM. Here is my code: #include <nanobind/nanobind.h>
#include <llvm-c/Core.h>
namespace nb = nanobind;
using namespace nb::literals;
NB_MODULE(llvmpym_ext, m) {
m.def("create_llvm_module", []() {
LLVMModuleRef mod = LLVMModuleCreateWithName("my_module");
return mod;
});
} When I build the extension, an error is emited:
Here is the definition code in Types.h /**
* The top-level container for all other LLVM Intermediate Representation (IR)
* objects.
*
* @see llvm::Module
*/
typedef struct LLVMOpaqueModule *LLVMModuleRef; And the code in Core.h
I've tried to use Edit: the following approaches also don't work correctly, reporting the same type of error: #include <nanobind/nanobind.h>
#include <llvm-c/Core.h>
#include <memory>
namespace nb = nanobind;
using namespace nb::literals;
// Define a wrapper class for the LLVMModuleRef
class LLVMModuleWrapper {
public:
LLVMModuleWrapper(LLVMModuleRef ref) : ref_(ref) {}
LLVMModuleRef get() const { return ref_; }
private:
LLVMModuleRef ref_;
};
NB_MODULE(llvmpym_ext, m) {
// Bind the wrapper class
nb::class_<LLVMModuleWrapper>(m, "LLVMModule")
.def("get", &LLVMModuleWrapper::get, nb::rv_policy::reference);
// Bind the function to create the LLVM module
m.def("create_llvm_module", []() {
LLVMModuleRef mod = LLVMModuleCreateWithName("my_module");
return std::make_unique<LLVMModuleWrapper>(mod);
});
} #include <nanobind/nanobind.h>
#include <llvm-c/Core.h>
namespace nb = nanobind;
using namespace nb::literals;
// Forward declaration of the opaque type
struct LLVMOpaqueModule;
NB_MODULE(llvmpym_ext, m) {
// Create an opaque type for LLVMModuleRef
nb::class_<LLVMOpaqueModule>(m, "LLVMModuleRef");
m.def("create_llvm_module", []() {
LLVMModuleRef mod = LLVMModuleCreateWithName("my_module");
return mod;
});
} |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
I find the solution. Just create a wrapper class/struct. Don't expose the LLVMModuleRef class outside. #include <nanobind/nanobind.h>
#include <nanobind/stl/string.h>
#include <llvm-c/Core.h>
namespace nb = nanobind;
using namespace nb::literals;
class PyLLVMModule {
public:
explicit PyLLVMModule(const std::string &name) {
module = LLVMModuleCreateWithName(name.c_str());
if (!module) {
throw std::runtime_error("Failed to create LLVM module");
}
}
~PyLLVMModule() {
if (module)
LLVMDisposeModule(module);
}
// Delete copy constructor and copy assignment
PyLLVMModule(const PyLLVMModule &) = delete;
PyLLVMModule &operator=(const PyLLVMModule &) = delete;
// Move constructor
PyLLVMModule(PyLLVMModule &&other) noexcept : module(other.module) {
other.module = nullptr;
}
// Move assignment
PyLLVMModule &operator=(PyLLVMModule &&other) noexcept {
if (this != &other) {
if (module) {
LLVMDisposeModule(module);
}
module = other.module;
other.module = nullptr;
}
return *this;
}
LLVMModuleRef get() {
return module;
}
void setModuleIdentifier(const std::string &identifier) {
LLVMSetModuleIdentifier(module, identifier.c_str(), identifier.size());
}
std::string getModuleIdentifier() const {
size_t len;
const char *identifier = LLVMGetModuleIdentifier(module, &len);
return std::string(identifier, len);
}
private:
LLVMModuleRef module;
};
NB_MODULE(llvmpym_ext, m) {
nb::class_<PyLLVMModule>(m, "PyLLVMModule")
.def(nb::init<const std::string &>(), "name"_a)
.def_prop_rw("identifier",
[](PyLLVMModule &m) { return m.getModuleIdentifier(); },
[](PyLLVMModule &m, const std::string &identifier)
{ m.setModuleIdentifier(identifier); });
}
|
Beta Was this translation helpful? Give feedback.
I find the solution. Just create a wrapper class/struct. Don't expose the LLVMModuleRef class outside.
Here is an example: