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

YOLOv2 C代码向Python脚本发布边界框数据编译报错求助

解决YOLOv2 C代码调用Python时的编译未定义引用问题

先看你的编译错误,大部分来自拼写错误和Python库链接不完整,还有代码逻辑的小问题,一步步来解决:

1. 修正C代码里的Python API拼写错误

你的代码里有几处Python API函数名大小写错误,这是导致undefined reference的直接原因:

  • 把pyTuple_SetItem改成PyTuple_SetItem(大写P),Python C API所有函数都是大写开头的标准命名
  • 把pyObject_CallMethod改成PyObject_CallMethod(大写P)

修改后的对应代码段:

//Setting the four arguments for the put() function
PyObject* pythonArgument;
pythonArgument = PyTuple_New(4);
PyTuple_SetItem(pythonArgument, 0, pyVal[0]);
PyTuple_SetItem(pythonArgument, 1, pyVal[1]);
PyTuple_SetItem(pythonArgument, 2, pyVal[2]);
PyTuple_SetItem(pythonArgument, 3, pyVal[3]);
//Calling put()
pyFunc = PyObject_CallMethod(pyModule, pyArgs[3], "O", pythonArgument);

另外,PyObject_CallMethod的参数格式需要注意:第三个参数是格式字符串,后面跟对应参数,所以要加上"O"来表示传入一个对象参数。

2. 修正Python初始化逻辑

你的draw_detections函数里每次都调用Py_Initialize()和Py_Finalize(),这不仅低效,还会导致Python环境重复初始化的问题。应该把Py_Initialize()移到initialize()函数里,只执行一次:

void initialize(){
 //先初始化Python环境,只执行一次
 Py_Initialize();
 //Setting the Path
 PySys_SetPath(pyArgs[0]);
 //Importing pynetworktables
 PyObject* pyName = PyString_FromString(pyArgs[1]);
 pyModule = PyImport_Import(pyName);
 Py_DECREF(pyName); //释放引用,避免内存泄漏
 //Calling init()
 PyObject* initFunc = PyObject_GetAttrString(pyModule, pyArgs[2]);
 if(initFunc && PyCallable_Check(initFunc)){
     PyObject_CallObject(initFunc, NULL);
     Py_DECREF(initFunc);
 }
}

然后在draw_detections里去掉Py_Initialize()和Py_Finalize(),可以在程序退出前(比如main函数结束时)统一调用Py_Finalize()。

3. 确保Makefile正确链接Python库

看你的编译输出,LDFLAGS里没有包含Python的链接参数,虽然Makefile里定义了PYTHON=1,但链接顺序有问题。修改Makefile里的$(EXEC)规则:

$(EXEC): $(EXECOBJ) $(ALIB)
 $(CC) $(COMMON) $(CFLAGS) $^ -o $@ $(LDFLAGS)

原来的命令重复加了$(ALIB),导致链接顺序错误,库应该放在编译对象之后。另外确认你的Python路径(Python2.7的aarch64架构路径)是正确的。

4. 修正Python脚本的变量作用域与参数错误

你的run_network.py里,init()函数的table是局部变量,put()函数无法访问,而且putNumber的调用格式错误,修正如下:

from networktables import NetworkTables

table = None  # 定义全局变量

def init():
    global table  # 声明使用全局变量
    NetworkTables.initialize('10.13.39.2')
    table = NetworkTables.getTable('Root')

def put(left, right, top, bot):  # 参数顺序和C代码传入的保持一致
    if table is not None:
        table.putNumber("left", left)
        table.putNumber("right", right)
        table.putNumber("top", top)
        table.putNumber("bot", bot)

注意:putNumber需要传递键名和对应数值两个参数,你原来的写法缺少键名,会导致运行时错误。

5. 其他优化细节

  • 释放Python对象的引用,比如Py_DECREF(pyLeft)、Py_DECREF(pythonArgument)等,避免内存泄漏
  • PyInt_FromSize_t:如果Python2.7中没有这个函数,可以换成PyInt_FromLong((long)left),因为left是int类型,转成long更安全

做完这些修改后,执行make clean && make重新编译,应该就能解决编译错误,成功将边界框数据传到Python脚本中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:53:45