[英]Python C-API: How to use the returned python dictionary in Objective-C?
My Python script app.py
has this function for example:例如,我的 Python 脚本
app.py
具有此功能:
def testmethod(x):
return {"steps":["hello","world"]}
I am using Python C-API in Objective-C as follows:我在 Objective-C 中使用 Python C-API 如下:
Py_Initialize();
PyObject *pName = PyUnicode_DecodeFSDefault("app");
PyObject* pModule = PyImport_Import(pName);
Py_DECREF(pName);
PyObject* myFunction = PyObject_GetAttrString(pModule,(char*)"testmethod");
PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(223.22));
PyObject* myResult = PyObject_CallObject(myFunction, args);
NSLog(@"Check for dict: %d",PyDict_Check(myResult)); // Prints true!!!!!!!!!!!! So definitely a dictionary
After this, I am not really sure how I can convert the myResult
to retrieve my dictionary.在此之后,我不太确定如何转换
myResult
以检索我的字典。 For doubles and strings, we usually use the PyFloat_AsDouble
and PyUnicode_AsUTF8String
, PyBytes_AsString
functions but I can't seem to find a PyBLAHBLAH_AsDict
or equivalent method.对于双打和字符串,我们通常使用
PyFloat_AsDouble
和PyUnicode_AsUTF8String
、 PyBytes_AsString
函数,但我似乎找不到PyBLAHBLAH_AsDict
或等效方法。
double result = PyFloat_AsDouble(myResult);
NSLog(@"Result: %f",result);*/
PyObject* pStrObj = PyUnicode_AsUTF8String(myResult);
char* zStr = PyBytes_AsString(pStrObj);
NSLog(@"String: %@",[NSString stringWithUTF8String:zStr]);
I don't have much experience with Objective-C so maybe I am not looking at the right place.我对 Objective-C 没有太多经验,所以也许我没有看对地方。
How can I convert the PyObject
to a NSDictionary?如何将
PyObject
转换为 NSDictionary?
I am basically looking for a C way of accessing the dictionary first (a map for example) which I can then use Objective-C methods to convert to NSDictionary.我基本上是在寻找一种首先访问字典的 C 方式(例如地图),然后我可以使用 Objective-C 方法将其转换为 NSDictionary。 Similar to how I used PyUnicode_AsUTF8String, PyBytes_AsString and stringWithUTF8String all combined together to get a NSString out of the Python String.
与我使用 PyUnicode_AsUTF8String 的方式类似,PyBytes_AsString 和 stringWithUTF8String 全部组合在一起以从 Python 字符串中获取 NSString。 Looking for something similar for dictionaries.
为字典寻找类似的东西。
I have figured out a way to achieve this but I don't know if this is the best possible way of doing this.我想出了一种方法来实现这一点,但我不知道这是否是最好的方法。 I modified my python script to use
json.dumps
to return a string representation of the dictionary.我修改了我的 python 脚本以使用
json.dumps
返回字典的字符串表示形式。 Then in my Objective-C code, I first get the string, then use JSONObjectWithData
to convert the json string to a NSDictionary.然后在我的 Objective-C 代码中,我首先获取字符串,然后使用
JSONObjectWithData
将 json 字符串转换为 NSDictionary。 This works for now but I am curious if there is a better way of doing this without having to return string instead of dictionary from Python.这现在有效,但我很好奇是否有更好的方法来做到这一点,而不必从 Python 返回字符串而不是字典。 This seems more like a workaround solution to me.
这对我来说更像是一种解决方法。 Here's what I have now:
这是我现在所拥有的:
app.py:应用程序.py:
import json
def testmethod(x):
return json.dumps({"steps":["hello","world"]})
Objective-C:目标-C:
Py_Initialize();
PyObject *pName = PyUnicode_DecodeFSDefault("app");
PyObject* pModule = PyImport_Import(pName);
Py_DECREF(pName);
PyObject* myFunction = PyObject_GetAttrString(pModule,(char*)"testmethod");
PyObject* args = PyTuple_Pack(1,PyFloat_FromDouble(223.22));
PyObject* myResult = PyObject_CallObject(myFunction, args);
PyObject* pStrObj = PyUnicode_AsUTF8String(myResult);
char* zStr = PyBytes_AsString(pStrObj);
NSString *jsonStr = [NSString stringWithUTF8String:zStr];
NSLog(@"String: %@",jsonStr);
NSError *error;
NSData *data = [jsonStr dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(@"Dictionary: %@",dictionary);
Use PyDict_Next
to iterate over key / value pairs of the dictionary.使用
PyDict_Next
迭代字典的键/值对。
You should also provide the Python hash and equality functions if you are still going to be using PyObject*
s.如果您仍打算使用
PyObject*
您还应该提供 Python 哈希和相等函数。 Otherwise, you should try and coerce them all into native types.否则,您应该尝试将它们全部强制转换为原生类型。
(This is in pseudo code since I don't really know Objective-C, but have used the C-Api and Python) (这是伪代码,因为我不太了解 Objective-C,但使用过 C-Api 和 Python)
NSObject* convert_py_object(PyObject* obj) {
if (PyDict_Check(obj)) return convert_py_dict(obj);
if (PyLong_Check(obj)) return convert_py_int(obj);
if (PyUnicode_Check(obj)) return convert_py_str(obj);
if (PyBytes_Check(obj)) return convert_py_bytes(obj);
if (PyList_Check(obj) || PyTuple_Check(obj) || PyIter_Check(obj)) return convert_py_list(obj);
throw error;
}
NSDictionary* convert_py_dict(PyObject* dict) {
if (!PyDict_Check(dict)) throw error;
NSDictionary* native_dict;
PyObject *key;
PyObject *value;
Py_ssize_t pos = 0;
while (PyDict_Next(self->dict, &pos, &key, &value)) {
native_dict[convert_py_object(key)] = convert_py_object(value);
}
return native_dict;
}
Another alternative would be to just use the Python API to access values of a dictionary.另一种选择是仅使用 Python API 来访问字典的值。 So iterate over all the values with
PyDict_Next
, PyDict_GetItemString
to access string items with simple char *
s, and PyDict_GetItem
to access an arbitrary Python value.因此,使用
PyDict_Next
、 PyDict_GetItemString
迭代所有值以访问具有简单char *
s 的字符串项,并使用PyDict_GetItem
访问任意 Python 值。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.