在C++中嵌入Python:无法将字符串或char*转换为numpy数组
Hey there! Let's figure out how to turn your C++ string/char* into a numpy array when embedding Python. I’ve got two solid approaches for you—pick the one that fits your workflow best:
If you want minimal changes to your existing C++ code, let Python do the string-to-numpy conversion. Just modify your Python function to split the input string, convert it to numerical values, and wrap it in a numpy array.
Example Python Function
import numpy as np def filter_func(input_str): # Split the comma-separated string into individual number strings num_strings = input_str.split(',') # Convert to floats and create a numpy array arr = np.array([float(s) for s in num_strings]) # Add your processing logic here... return arr
Your C++ Code (Almost Unchanged)
Keep your existing C++ code that passes the string to Python—now when you call filterFunc, the input gets converted to a numpy array inside Python automatically:
const char* blu = "1,2,3,4,5,6,7,8,9"; PyObject* args = Py_BuildValue("(s)", blu); if (!args) { PyErr_Print(); Py_DECREF(filterFunc); qDebug()<<"Error building args tuple"; return; } PyObject* resultObj = PyObject_CallObject(filterFunc, args); // Clean up references Py_DECREF(args);
This is great for quick prototyping or if you don’t need to manipulate the numpy array directly in C++.
For better performance (especially with large datasets) or if you need full control over the array creation in C++, use numpy’s C API to build the array directly.
Step 1: Set Up Numpy C API
First, include the numpy headers and initialize the API (must be done after Py_Initialize()):
#include <numpy/arrayobject.h> #include <sstream> #include <vector> // Initialize numpy's C API (call this once after Py_Initialize()) import_array();
Step 2: Parse String to Numerical Data & Build Numpy Array
const char* blu = "1,2,3,4,5,6,7,8,9"; // Parse the comma-separated string into a vector of floats std::vector<float> values; std::stringstream ss(blu); std::string token; while (std::getline(ss, token, ',')) { try { values.push_back(std::stof(token)); } catch (const std::exception& e) { qDebug() << "Failed to parse number:" << token.c_str(); // Handle error appropriately return; } } // Define the array shape (1D array with length equal to values.size()) npy_intp dims[1] = {static_cast<npy_intp>(values.size())}; // Create the numpy array from our C++ data buffer PyObject* numpyArray = PyArray_SimpleNewFromData( 1, // Number of dimensions dims, // Array shape NPY_FLOAT, // Data type (use NPY_DOUBLE for double-precision) values.data() // Pointer to our numerical data ); // Critical: Tell numpy we own the data buffer (so it doesn't try to free it) // If you want numpy to take ownership of the data, use PyArray_SetBaseObject with a PyObject wrapper PyArray_SetBaseObject((PyArrayObject*)numpyArray, NULL); // Pass the numpy array to your Python function PyObject* args = Py_BuildValue("(O)", numpyArray); if (!args) { PyErr_Print(); Py_DECREF(filterFunc); Py_DECREF(numpyArray); qDebug()<<"Error building args tuple"; return; } PyObject* resultObj = PyObject_CallObject(filterFunc, args); // Clean up all references to avoid memory leaks Py_DECREF(args); Py_DECREF(numpyArray);
Key Notes for This Approach:
- Linking Numpy: When compiling, make sure to link against numpy’s libraries (use
pkg-config --libs numpyor specify the library path manually). - Memory Management:
PyArray_SimpleNewFromDatadoesn’t take ownership of your data buffer by default—you’re responsible for keepingvaluesalive untilnumpyArrayis no longer used. If you want numpy to handle memory cleanup, wrap your data in aPyBytesobject and usePyArray_SetBaseObject. - Error Checking: Always check if numpy API calls return
NULL—usePyErr_Print()to debug any issues.
内容的提问来源于stack exchange,提问作者Alok

