Car*_*izz 3 c python struct cython
我试图在 Cython 中调用 C 函数,标题如下所示:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
#include <ctype.h>
#include <unistd.h>
#include <math.h>
#include <apriltag.h>
#include <tag36h11.h>
#include <common/getopt.h>
#include <common/image_u8.h>
#include <common/image_u8x4.h>
#include <common/pjpeg.h>
#include <common/zarray.h>
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我想返回一个结构数组,其类型定义为apriltag_detection_t
. 根据文档,为了能够在 Cython 中使用它,我必须定义某种pxd
文件,它本质上是标头的副本。
然而,apriltag_detection_t
是一个已经在 中定义的类型apriltag.h
。此外,apriltag_detection_t
具有已在 中定义的成员apriltag.h
。在能够使用此库之前,我是否必须在 Cython 文件中递归地重新定义所有这些类型(手动)?我该把它们写在哪里?
谢谢!
更新6
终于到了包装函数的步骤了!
from libc.stdint cimport uint8_t
cdef extern from "<apriltag.h>":
cdef struct apriltag_detection:
int id
double c[2]
double p[4][2]
ctypedef apriltag_detection apriltag_detection_t
cdef extern from "tag36h11_detector/tag36h11_detector.h":
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
def detect(width, height, frame):
return scan_frame(width, height, frame)
Run Code Online (Sandbox Code Playgroud)
tag36h11_detector.pyx:15:21:无法将“apriltag_detection_t *”转换为Python对象
apriltag_detection_t*
是一个结构数组
更新 5 这似乎有效。
from libc.stdint cimport uint8_t
cdef extern from "<apriltag.h>":
cdef struct apriltag_detection:
int id
double c[2]
double p[4][2]
ctypedef apriltag_detection apriltag_detection_t
cdef extern from "tag36h11_detector/tag36h11_detector.h":
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
Run Code Online (Sandbox Code Playgroud)
更新 4 通过导入必要的类型解决了以前的问题。
from libc.stdint cimport uint8_t
cdef extern from "apriltag.h":
cdef struct apriltag_detection:
int id
double c[2]
double p[4][2]
ctypedef apriltag_detection apriltag_detection_t
cdef extern from "tag36h11_detector.h":
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
Run Code Online (Sandbox Code Playgroud)
tag36h11_detector.c:533:10:致命错误:找不到“apriltag.h”文件
我不确定这是从哪里来的,因为我的头文件(如原始帖子中提供的)是必需的<apriltag.h>
而不是"apriltag.h"
. 这就是我的setup.py
样子。
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules=cythonize(Extension(\
name='tag36h11_detector', \
sources=["tag36h11_detector.pyx", \
"tag36h11_detector/tag36h11_detector.c"], \
include_path=["/usr/local/include/apriltag"], \
libraries=["apriltag"])))
Run Code Online (Sandbox Code Playgroud)
更新3
cdef extern from "apriltag.h":
cdef struct apriltag_detection:
int id
double c[2]
double p[4][2]
ctypedef apriltag_detection apriltag_detection_t
cdef extern from "tag36h11_detector.h":
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
Run Code Online (Sandbox Code Playgroud)
tag36h11_detector.pyx:10:60: 'uint8_t' 不是类型标识符
更新2
这是我当前的代码,以下是编译错误
// tag36h11_detector.pyx
cdef extern from "apriltag.h":
ctypedef apriltag_detection_t:
int id
double c[2]
double p[4][2]
cdef extern from "tag36h11_detector.h":
apriltag_detection_t* scan_frame(int width, int height, uint8_t* data);
// apriltag.h
...
typedef struct apriltag_detector apriltag_detector_t;
...
Run Code Online (Sandbox Code Playgroud)
tag36h11_detector.pyx:2:33:ctypedef 语句中的语法错误
更新1
因此,我尝试使用 Python(我编写和实现的)与上面的头文件进行交互,其中类型定义在apriltag.h
(来自库)中。
cdef extern from "apriltag.h":
struct apriltag_detection:
int id
double c[2]
double p[4][2]
cdef extern from "tag36h11_detector.h":
struct apriltag_detection* scan_frame(int width, int height, uint8_t* data);
Run Code Online (Sandbox Code Playgroud)
当我尝试编译上述内容时,我得到
tag36h11_detector.pyx:8:29:结构或联合定义中存在语法错误
cython 文档的这一部分基本上涵盖了这一点,它表示您只需要导入将在 cython 代码中使用的部分。
例如,让我们看一下以下 C 接口:
#struct.h
struct Needed{
int a;
};
struct NotNeeded{
int b;
};
struct Combined{
struct Needed needed;
struct NotNeeded notneeded;
};
struct Combined create(void);
Run Code Online (Sandbox Code Playgroud)
您想调用该函数并使用结构中的create
值,这意味着您必须导入和 的一部分,但不在您的 cython 代码中:a
Needed
struct Needed
struct Combined
NotNeeded
#struct_import.pyx
cdef extern from "struct.h":
struct Needed: # use "ctypedef struct Needed" if defined with typedef in h-file!
int a
struct Combined: #NotNeeded is missing!
Needed needed
Combined create()
def get_needed():
return create().needed.a #should be 42!
Run Code Online (Sandbox Code Playgroud)
现在,使用setup.py
(其内容可以在下面进一步看到,to的内容也是如此struct.c
)我们得到了预期的结果:
[] python setup.py build_ext --inplace
[] python -c "python -c "import struct_import as si; print si.get_needed()"
42
Run Code Online (Sandbox Code Playgroud)
如果您使用 cython 将一些 C 代码粘合在一起,这是可能的,甚至更少。在我们的示例中,如果我们有一个 C 函数,可以从Combined
结构中提取所需的值:
#struct.h
...
int extract(struct Combined combined);//returns combined.needed.a
Run Code Online (Sandbox Code Playgroud)
我们可以在 pyx 文件中按如下方式使用它:
#struct_import.pyx
cdef extern from "struct.h":
struct Combined:
pass #nothing imported!
Combined create()
int extract(Combined combined)
def get_needed():
return extract(create()) #should be 42!
Run Code Online (Sandbox Code Playgroud)
Needed
尽管我们根本没有导入该结构,但它的效果与第一个版本一样好。
因此,如果导入所有这些结构变得一件苦差事,则可以扩展 c 接口以使其不必要。
为了使示例完整,这里缺少 setup.py 和 struct.c 文件:
#setup.py:
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules=cythonize(Extension(
name='struct_import',
sources = ["struct_import.pyx", "struct.c"]
)))
Run Code Online (Sandbox Code Playgroud)
和
//struct.c
#include "struct.h"
struct Combined create(){
struct Combined res;
res.needed.a=42;
res.notneeded.b=21;
return res;
}
int extract(struct Combined combined){
return combined.needed.a;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
2231 次 |
最近记录: |