113 lines
3.7 KiB
C++
113 lines
3.7 KiB
C++
#include <boost/python/module.hpp>
|
||
#include <boost/python/def.hpp>
|
||
#include <numpy/arrayobject.h>
|
||
#include <stdio.h>
|
||
|
||
|
||
#include "./util/RTCContext.h"
|
||
namespace py = boost::python;
|
||
|
||
int init(const char* selfUserId, const char* selfDisplayName, const char* selfRoomId, boost::python::object callback) {
|
||
RTCContext::instance().setPyCallback(callback);
|
||
bool res = RTCContext::instance().init(selfUserId, selfDisplayName, selfRoomId);
|
||
if (res) {
|
||
return 0;
|
||
} else {
|
||
return -1;
|
||
}
|
||
}
|
||
int initRecv(const char* destRoomId, const char* srcUserId, const int16_t destChannelIndex) {
|
||
bool res = RTCContext::instance().initRecv(destRoomId, srcUserId, destChannelIndex);
|
||
if (res) {
|
||
return 0;
|
||
} else {
|
||
return -1;
|
||
}
|
||
}
|
||
int initSend(const char* destRoomId, const int16_t destChannelIndex) {
|
||
bool res = RTCContext::instance().initSend(destRoomId, destChannelIndex);
|
||
if (res) {
|
||
return 0;
|
||
} else {
|
||
return -1;
|
||
}
|
||
}
|
||
py::object create_numpy_array() {
|
||
// 初始化 NumPy C API(必须调用)
|
||
import_array();
|
||
|
||
// 创建 1D 数组(int32 类型)
|
||
npy_intp dims[1] = {4};
|
||
int32_t data[4] = {1, 2, 3, 4};
|
||
|
||
// 从现有内存创建数组(不拷贝数据)
|
||
PyObject* py_array = PyArray_SimpleNewFromData(
|
||
1, dims, NPY_INT32, data
|
||
);
|
||
|
||
// 转换为 boost::python::object
|
||
py::object py_data = py::handle<>(py_array);
|
||
|
||
// 注意:需确保 data 的生命周期长于 py_data
|
||
return py_data;
|
||
}
|
||
int sendCustomAudioData(const int16_t destChannelIndex, py::object pD, int32_t sampleRate, uint64_t channelNum,
|
||
uint64_t dataLen) {
|
||
try {
|
||
pyData = create_numpy_array();
|
||
std::cout << "step 1" << std::endl;
|
||
// 1. 检查输入有效性
|
||
if (pyData.ptr() == nullptr) {
|
||
throw std::runtime_error("Input data is NULL");
|
||
}
|
||
|
||
std::cout << "step 2" << std::endl;
|
||
std::cout << "pyData ptr is:" << pyData.ptr() << std::endl;
|
||
// 2. 检查是否是 numpy 数组
|
||
if (!PyObject_Check(pyData.ptr())) {
|
||
std::cerr << "ERROR: Not a valid Python object" << std::endl;
|
||
throw std::runtime_error("Invalid Python object");
|
||
}
|
||
std::cout << "step 2" << std::endl;
|
||
if (!PyArray_Check(pyData.ptr())) {
|
||
std::cout << "input is notnumpy" << std::endl;
|
||
throw std::runtime_error("Input is not a numpy array");
|
||
}
|
||
|
||
std::cout << "step 3" << std::endl;
|
||
// 3. 转换为 PyArrayObject
|
||
PyArrayObject* npArray = reinterpret_cast<PyArrayObject*>(pyData.ptr());
|
||
|
||
std::cout << "step 4" << std::endl;
|
||
// 4. 检查数据类型是否为 int16
|
||
if (PyArray_TYPE(npArray) != NPY_INT16) {
|
||
throw std::runtime_error("Array must be of type int16 (np.int16)");
|
||
}
|
||
|
||
std::cout << "step 5" << std::endl;
|
||
// 5. 检查数据是否连续
|
||
if (!PyArray_ISCONTIGUOUS(npArray)) {
|
||
throw std::runtime_error("Array must be contiguous in memory");
|
||
}
|
||
std::cout << "step 6" << std::endl;
|
||
|
||
// 6. 获取数据指针
|
||
void* dataPtr = PyArray_DATA(npArray);
|
||
if (dataPtr == nullptr) {
|
||
throw std::runtime_error("Invalid data pointer");
|
||
}
|
||
std::cout << "step 7" << std::endl;
|
||
return RTCContext::instance().sendCustomAudioData(destChannelIndex, dataPtr, sampleRate, channelNum, dataLen);
|
||
|
||
} catch (const std::exception& e) {
|
||
std::cout << "error:" << e.what() << std::endl;
|
||
return -1;
|
||
}
|
||
}
|
||
|
||
BOOST_PYTHON_MODULE(rtc_plugins) {
|
||
py::def("init", &init);
|
||
py::def("initRecv", &initRecv);
|
||
py::def("initSend", &initSend);
|
||
py::def("sendCustomAudioData", &sendCustomAudioData);
|
||
} |