से structs की सरणी पास करें [अद्यतन: समस्या हल हो गई! पोस्ट के निचले]पाइथन से सी
मैं अजगर डेवलपर्स मेरी एपीआई, जो सी ++ पायथन सी एपीआई के माध्यम से मैन्युअल रूप से अवगत कराया इंटरफेस की एक श्रृंखला है में पैक डेटा की एक सरणी (इस मामले कोने में) पारित करने के लिए अनुमति देने के लिए की आवश्यकता है।
class Vertex(Structure):
_fields_ = [
('x', c_float),
('y', c_float),
('z', c_float),
('u', c_float),
('v', c_float),
('color', c_int)
]
verts = (Vertex * 3)()
verts[0] = Vertex(0.0, 0.5, 0.0, 0.0, 0.5, 0xFF0000FF)
verts[1] = Vertex(0.5, -0.5, 0.0, 0.5, -0.5, 0x00FF00FF)
verts[2] = Vertex(-0.5, -0.5, 0.0, -0.5, -0.5, 0x0000FFFF)
device.ReadVertices(verts, 3) # This is the interfaces to the C++ object
कहाँ समारोह मैं करने के लिए पारित करने के लिए कोशिश कर रहा हूँ निम्नलिखित हस्ताक्षर हैं:
void Device::ReadVertices(Vertex* verts, int count);
और इस के साथ मेरी प्रारंभिक छाप इस तरह एक अंतरफलक के लिए अनुमति देने के लिए ctypes संरचना वर्ग का उपयोग करने के लिए है अजगर आवरण इस तरह दिखता है:
static PyObject* Device_ReadVertices(Py_Device* self, PyObject* args)
{
PyObject* py_verts;
int count;
if(!PyArg_ParseTuple(args, "Oi", &py_verts, &count))
return NULL;
// This Doesn't Work!
Vertex* verts = static_cast<Vertex*>(PyCObject_AsVoidPtr(py_verts));
self->device->ReadVertices(verts, count);
Py_RETURN_NONE;
}
बेशक
, सबसे बड़ी समस्या मैं यह है: मैं struct के लिए PyObject प्राप्त कर सकते हैं, लेकिन मैं पता नहीं कैसे मैं यह करने के लिए डाली होता है सही प्रकार उपरोक्त कोड बुरी तरह विफल रहता है। तो मैं उपयोगकर्ता को इस तरह के डेटा को पायथन से पास करने की इजाजत देने के बारे में कैसे कहूंगा?
अब, कुछ चीजों पर विचार करने के लिए: सबसे पहले यह है कि मेरे पास पहले से ही मेरी पाइथन/सी ++ परत लिखी गई है, और मैं इसके साथ पूरी तरह से खुश हूं (मैं एसडब्ल्यूआईजी से दूर चले गए ताकि मुझे और अधिक लचीलापन मिल सके)। मैं इसे फिर से कोड नहीं करना चाहता, इसलिए मैं एक समाधान पसंद करूंगा जो सी एपीआई के साथ काम करता है। दूसरा, मेरा इरादा है कि वेरटेक्स संरचना को मेरे सी ++ कोड में पूर्व-परिभाषित किया जाए, इसलिए मैं उपयोगकर्ता को पायथन में इसे फिर से परिभाषित करने की आवश्यकता नहीं रखूंगा (इस तरह त्रुटियों पर कटौती), लेकिन मैं हूं सुनिश्चित नहीं है कि इस तरह एक संगत संरचना का पर्दाफाश कैसे करें। तीसरा, मेरे पास ऐसा करने का एक और तरीका नहीं जानने से सीटीपीएस संरचना को अलग करने का कोई कारण नहीं है। किसी भी सुझाव का स्वागत है। आखिरकार, चूंकि यह एक ग्राफिक्स ऐप के लिए है (जैसा कि आपने अनुमान लगाया होगा), मैं एक सुविधाजनक विधि पर एक तेज विधि पसंद करूंगा, भले ही तेज विधि थोड़ा और काम करे।
किसी भी मदद के लिए धन्यवाद! मैं अभी भी पाइथन एक्सटेंशन के आसपास अपना रास्ता महसूस कर रहा हूं, इसलिए कुछ स्टिकियर भागों पर सामुदायिक इनपुट प्राप्त करने में यह बहुत मददगार है।
[समाधान]
तो सबसे पहले बंद, हर किसी के लिए धन्यवाद, जो अपने विचारों में खड़ा किया। यह बहुत कम tidbits था जो अंतिम जवाब में जोड़ा गया। अंत में मुझे जो मिला वह है: सैम का स्ट्रक्चर.pack का उपयोग करने का सुझाव पैसे पर सही रहा। यह देखते हुए कि मैं अजगर 3 उपयोग कर रहा हूँ, मैं इतना थोड़ा कभी यह बदलाव करने के लिए किया था, लेकिन जब सभी ने कहा था और किया यह वास्तव में अपनी स्क्रीन पर दिखाया जा रहा एक त्रिकोण है:
verts = bytes()
verts += struct.pack("fffffI", 0.0, 0.5, 0.0, 0.0, 0.5, 0xFF0000FF)
verts += struct.pack("fffffI", 0.5, -0.5, 0.0, 0.5, -0.5, 0x00FF00FF)
verts += struct.pack("fffffI", -0.5, -0.5, 0.0, -0.5, -0.5, 0x0000FFFF)
device.ReadVertices(verts, 3)
मेरी टपल पार्स अब की तरह लग रही के साथ
इस:
static PyObject* Device_ReadVertices(Py_Device* self, PyObject* args)
{
void* py_verts;
int len, count;
if(!PyArg_ParseTuple(args, "y#i", &py_verts, &len, &count))
return NULL;
// Works now!
Vertex* verts = static_cast<Vertex*>(py_verts);
self->device->ReadVertices(verts, count);
Py_RETURN_NONE;
}
नोट है कि भले ही मैं इस उदाहरण में len
चर का उपयोग नहीं करते हैं (हालांकि मैं होगा अंतिम उत्पाद में) मैं तो बस 'y' के बजाय 'वाई #' का उपयोग कर टपल पार्स करने के लिए की जरूरत है अन्यथा यह पहले न्यूल (दस्तावेज़ीकरण के अनुसार) पर रुक जाएगा। यह भी माना जा सकता है: शून्य * इस तरह कास्ट काफी खतरनाक है, इसलिए कृपया यहां दिखाए जाने से अधिक त्रुटि जांच लोड करें!
तो, अच्छी तरह से काम किया, खुश दिन, पैक और घर जाओ, हाँ?
रुको! इतना शीघ्र नही! अभी और है!
इस बारे में अच्छा लगा कि यह सब कैसे काम करता है, मैंने देखा कि मेरा पिछला प्रयास अभी भी मुझ पर उड़ा है और इस पोस्ट में पाइथन के पहले स्निपेट पर वापस लौटा है। (बिल्कुल नए सी कोड का उपयोग कर) और ... यह काम किया! परिणाम struct.pack संस्करण के समान थे! वाह!
तो इसका मतलब है कि आपके उपयोगकर्ताओं के पास इस तरह का डेटा प्रदान करने के तरीके में कोई विकल्प है, और आपका कोड या तो कोई बदलाव नहीं कर सकता है। व्यक्तिगत रूप से मैं ctype को प्रोत्साहित करने जा रहा हूं। संरचना विधि, क्योंकि मुझे लगता है कि यह आसान पठनीयता के लिए बनाता है, लेकिन वास्तव में यह भी है कि उपयोगकर्ता जो भी आरामदायक है। (हेक, वे मैन्युअल रूप से हेक्स में बाइट्स की एक स्ट्रिंग टाइप कर सकते हैं। यह काम करता है। मैंने कोशिश की।)
ईमानदारी से मुझे लगता है कि यह सबसे अच्छा संभव परिणाम है, इसलिए मैं उत्साहित हूं। आप सभी को धन्यवाद, और इस समस्या में चलने वाले किसी और को शुभकामनाएँ!
क्या आपने boost :: python का उपयोग करने पर विचार किया है? – Anycorn
हां, मैंने SWIG की कोशिश करने से पहले इसे आजमाया। मुझे एसडब्ल्यूआईजी का उपयोग करना आसान हो गया (बहुत कम अतिरिक्त कोड और आपको समान प्रदर्शन के साथ चलने वाले राक्षसों को संकलित करने की आवश्यकता नहीं है)। अंत में, हालांकि, मैं SWIG की तुलना में अधिक नियंत्रण चाहता था (उदाहरण के लिए, एसडब्ल्यूआईजी आपको पाइथन गुणों का पर्दाफाश करने का कोई रास्ता नहीं देता है) और इसलिए रैपर करने के लिए चुना गया था, जो वास्तव में आपको एक बार दर्द रहित होने के बाद बाहर निकला मूल बातें नीचे, मेरे कोड का उल्लेख नहीं करना अब बहुत तेज है। :) – Toji
अनुमोदित, वे उन दोनों के लिए अच्छी पुस्तकालय हैं जो सी-एपीआई को दुबला नहीं करना चाहते हैं। वे सिर्फ मेरी जरूरतों के अनुरूप नहीं थे। – Toji