You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用pybind11封装Go代码制Python库时遇ImportError求助

问题:通过pybind11调用Go代码生成Python库时遇ImportError

场景与操作步骤

  • 在Anaconda虚拟环境goscraper中安装pybind11,使用VSCode开发
  • 创建add.go文件,编写导出的Go函数
  • 执行go build -o addlib.dll -buildmode=c-shared add.go生成addlib.dll和addlib.h
  • 创建addlib.cpp,编写pybind11绑定代码
  • 配置c_cpp_properties.json添加头文件路径
  • 编写CMakeLists.txt,通过VS2022 MSVC开发者命令提示符在build目录执行cmake ..和cmake --build .编译

错误信息

导入生成的Python库时出现:

ImportError: dynamic module does not define module export function

相关代码

add.go

package main

import "C"
import "fmt"

//export Add
func Add(a int, b int) int {
    return a + b
}

//export Greet
func Greet() {
    fmt.Println("Hello world")
}

func main() { }

addlib.cpp

#include <pybind11/pybind11.h>

extern "C" {
    #include "addlib.h"
}

namespace py = pybind11;

int add(int a, int b) {
    return Add(a, b); 
}

void greet() {
    Greet();
}

PYBIND11_MODULE(Go_Pybind_practice_v2, m) {
    m.def("add", &add, "Add two integers");
    m.def("greet", &greet, "Print greeting from Go");
}

c_cpp_properties.json

{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**",
                "C:\\dev\\go_pybind_practice_v3\\pybind11\\include\\pybind11", // for pybind11.h
                "C:\\Users\\accra\\.conda\\envs\\goscraper\\include", // for Python.h
                "C:\\Users\\accra\\.conda\\envs\\goscraper\\Library\\share\\cmake\\pybind11" // for pybind11Config.cmake
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"
            ],
            "windowsSdkVersion": "10.0.22621.0",
            "compilerPath": "cl.exe",
            "cStandard": "c17",
            "cppStandard": "c++17",
            "intelliSenseMode": "windows-msvc-x64"
        }
    ],
    "version": 4
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(go_pybind_practice_v3)

set(pybind11_DIR "C:\\Users\\accra\\.conda\\envs\\goscraper\\Library\\share\\cmake\\pybind11")

find_package(pybind11 REQUIRED)

pybind11_add_module(go_pybind_practice_v3 addlib.cpp)
target_link_libraries(go_pybind_practice_v3 PRIVATE pybind11::module "C:\\dev\\go_pybind_practice_v3\\addlib.lib")

addlib.h

/* Code generated by cmd/cgo; DO NOT EDIT. */

/* package command-line-arguments */


#line 1 "cgo-builtin-export-prolog"

#include <stddef.h>

#ifndef GO_CGO_EXPORT_PROLOGUE_H
#define GO_CGO_EXPORT_PROLOGUE_H

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef struct { const char *p; ptrdiff_t n; } _GoString_;
#endif

#endif

/* Start of preamble from import "C" comments.  */




/* End of preamble from import "C" comments.  */


/* Start of boilerplate cgo prologue.  */
#line 1 "cgo-gcc-export-header-prolog"

#ifndef GO_CGO_PROLOGUE_H
#define GO_CGO_PROLOGUE_H

typedef signed char GoInt8;
typedef unsigned char GoUint8;
typedef short GoInt16;
typedef unsigned short GoUint16;
typedef int GoInt32;
typedef unsigned int GoUint32;
typedef long long GoInt64;
typedef unsigned long long GoUint64;
typedef GoInt64 GoInt;
typedef GoUint64 GoUint;
typedef size_t GoUintptr;
typedef float GoFloat32;
typedef double GoFloat64;
#ifdef _MSC_VER
#include <complex.h>
typedef _Fcomplex GoComplex64;
typedef _Dcomplex GoComplex128;
#else
typedef float _Complex GoComplex64;
typedef double _Complex GoComplex128;
#endif

/*
  static assertion to make sure the file is being used on architecture
  at least with matching size of GoInt.
*/
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1];

#ifndef GO_CGO_GOSTRING_TYPEDEF
typedef _GoString_ GoString;
#endif
typedef void *GoMap;
typedef void *GoChan;
typedef struct { void *t; void *v; } GoInterface;
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice;

#endif

/* End of boilerplate cgo prologue.  */

#ifdef __cplusplus
extern "C" {
#endif

extern __declspec(dllexport) GoInt Add(GoInt a, GoInt b);
extern __declspec(dllexport) void Greet();

#ifdef __cplusplus
}
#endif

解决方案

1. 修正模块名称不匹配问题

这是触发错误的核心原因:

  • CMakeLists.txt中pybind11_add_module指定的模块名是go_pybind_practice_v3
  • addlib.cpp中PYBIND11_MODULE的第一个参数是Go_Pybind_practice_v2

两者必须完全一致,Python导入时会寻找与模块名对应的导出函数。修改其中一处使名称统一,比如将PYBIND11_MODULE的名称改为go_pybind_practice_v3:

PYBIND11_MODULE(go_pybind_practice_v3, m) {
    m.def("add", &add, "Add two integers");
    m.def("greet", &greet, "Print greeting from Go");
}

2. 修正类型匹配问题

Go生成的Add函数参数和返回值是GoInt(对应long long),但当前cpp中的add函数使用int类型,可能导致类型截断。修改cpp中的类型匹配:

#include <pybind11/pybind11.h>

extern "C" {
    #include "addlib.h"
}

namespace py = pybind11;

GoInt add(GoInt a, GoInt b) {
    return Add(a, b); 
}

void greet() {
    Greet();
}

PYBIND11_MODULE(go_pybind_practice_v3, m) {
    m.def("add", &add, "Add two integers");
    m.def("greet", &greet, "Print greeting from Go");
}

3. 确保Go生成的DLL可被加载

编译完成后,将addlib.dll复制到生成的.pyd文件所在目录,或者将addlib.dll的路径添加到系统PATH环境变量中,否则Python导入模块时会找不到依赖的Go动态库。

内容的提问来源于stack exchange,提问作者Mark Kim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:33:21