通过 python 扩展/包装器传递浮点数组指针 – SndObj-library

Posted

技术标签:

【中文标题】通过 python 扩展/包装器传递浮点数组指针 – SndObj-library【英文标题】:Passing a float array pointer through a python extension/wrapper – SndObj-library 【发布时间】:2015-09-14 17:28:44 【问题描述】:

所以我觉得 Google 已经厌倦了试图帮助我解决这个问题。

我最近一直在尝试使用 SndObj 库,更具体地说是它的 python 包装器。

这个库很好地包含了一个 python 示例来玩,唯一的问题是让它工作。下面的最后一行给了我一个受伤的世界:

from sndobj import SndObj, SndRTIO, HarmTable, Oscili, SND_OUTPUT
from scipy import zeros, pi, sin, float32
import numpy

sine = numpy.array([256],float32)
for i in range(sine.size):
    sine[i] = 0.5 * sin((2 * pi * i) / sine.size)
    sine *= 32768

obj = SndObj()
obj.PushIn(sine,256)

在原始代码中是:

obj.PushIn(sine)

这给了我错误

TypeError: SndObj_PushIn() 只需要 3 个参数(给定 2 个)

好吧,够公平的。我检查了(自动生成的)文档和网络上的一些示例代码,发现它也需要一个整数 size。言归正传(我喜欢他们的做法,我猜至少是示例中过时的代码)。

无论如何,新的论点;新错误:

TypeError:在方法“SndObj_PushIn”中,类型为“float *”的参数 2

我完全没有使用 c++ 的经验,我相信它是库的“原生”(请原谅我缺乏正确的术语)语言,但我很确定我已经知道它需要一个浮点数组/ vector 作为它的第二个参数(第一个是 self)。但是,我很难做到这一点。我不是已经有一个浮点数组/向量了吗?除其他外,我还尝试在第一行使用 float 而不是 float32 并在第四行使用 float(32768) 到否有用。

任何帮助、建议或提示将不胜感激!

编辑: 不确定浮点向量/数组部分并再次查看自动文档:

int SndObj::PushIn  (   float *     vector,
int     size 
)

所以我会说至少 c++ 需要一个浮点数组/向量,尽管我当然仍然对 python 包装器有误。

更新 根据 Prune 的要求(说错误消息不是要求浮点向量,而是说这是错误),我尝试输入不同的整数(intint32等)向量代替。但是,看到我仍然收到相同的错误消息并牢记上面的 EDIT,我想说它实际上应该是一个浮点向量。

更新2 在 saulspatz 的一些提示之后,我更改了问题的标题和标签,以更好地表述我的问题。我也根据这个做了一些进一步的谷歌搜索,但还没有挖掘出任何有用的东西。

UDATE3 已解决

【问题讨论】:

【参考方案1】:

实际上,问题恰恰相反:PushIn 接受一个整数数组。错误消息是抱怨你给它浮动。试试这个来代替你对 PushIn 的调用

int_sine = numpy.array([256],int32)
int_sine = [int(x) for x in sine]

然后将 int_sine 而不是正弦输入 PushIn。

【讨论】:

感谢您的快速答复!这确实可以解释很多!但是我仍然收到完全相同的错误消息...我还检查了数组中包含的类型,以确保它是int32。我也尝试了 int,但没有任何区别。【参考方案2】:

我对你的问题没有真正的答案,但我有一些信息太长,无法在评论中显示,我认为这些信息可能会很有用。我查看了我认为是最新版本 SndObj 2.6.7 的来源。在 SndObj.h 中,PushIn 的定义是

  int PushIn(float *in_vector, int size)
    for(int i = 0; i<size; i++)
      if(m_vecpos >= m_vecsize) m_vecpos = 0;
      m_output[m_vecpos++] = in_vector[i];
    
    return m_vecpos;
  

所以很明显size 是要推送的元素数。 (我认为这将是数组中元素的数量,256 是正确的。)float* 表示指向浮点数的指针; in_vector 只是一个标识符。我阅读了错误消息,表示该函数在期待一个浮点指针时收到了一个浮点数。在 C++ 程序中,您可以通过传递浮点数数组的名称来传递指向浮点数的指针,但这不是唯一的方法。

我对 python 扩展是如何编程的一无所知,很抱歉。在我看来,obj.PushIn(sine,256) 看起来不错,但这是一种幼稚的看法。

也许有了这些信息,您可以制定另一个问题(或找到另一个标签),这将吸引知道用 C/C++ 编写 python 扩展的人的注意力。

我希望这会有所帮助。

【讨论】:

很棒的信息,非常感谢!我会对此进行一些研究。 @JohanPL 不客气。当你找到答案时,请告诉我。你激起了我的好奇心。【参考方案3】:

所以终于设法让它工作了(在非常友好的包装作者的帮助下)!

事实证明,沙盒库中有一个 floatArray 类,用于将浮点数组传递给 c++ 函数。我猜他们在写完 numpy-test.py 之后就包含了,这让我陷入了循环。

功能代码:

from sndobj import SndObj, SndRTIO, SND_OUTPUT, floatArray
from scipy import pi, sin

# ---------------------------------------------------------------------------
# Test PushIn

# Create 1 frame of a sine wave in a numpy array
sine = floatArray(256)
for i in range(256):
     sine[i] = float(32768*0.5 * sin((2 * pi * i) / 256))

obj = SndObj()
obj.PushIn(sine,256)

outp = SndRTIO(1, SND_OUTPUT)
outp.SetOutput(1, obj)

# Repeatedly output the 1 frame of sine wave
duration = outp.GetSr() * 2  # 2 seconds
i = 0
vector_size = outp.GetVectorSize()
while i < duration:
    outp.Write()
    i += vector_size

【讨论】:

以上是关于通过 python 扩展/包装器传递浮点数组指针 – SndObj-library的主要内容,如果未能解决你的问题,请参考以下文章

SWIG C++ Python:通过引用或指针包装 int

swig-php 包装器使用指针,c 代码是一个数组

使用 CFFI 从 Python 传递指向 C 函数的指针的最佳方法

在 C++ 中创建对象并将指针传递给 python

使用 SWIG 将 C++ 对象指针传递给 Python,而不是再次返回 C++

Python从门到精通:包装-03-对象处理