Спасибо! с custom_string_to_python_str я еще как-то смог по форумам нарыть, а вот с обратным как-то не осилил.
code:
// Convert obj_ptr into a QString
static void construct(
PyObject* obj_ptr,
boost::python::converter::rvalue_from_python_stage1_data* data)
{
// Extract the character data from the python string
const char* value = PyString_AsString(obj_ptr);
// Verify that obj_ptr is a string (should be ensured by convertible())
assert(value);
// Grab pointer to memory into which to construct the new QString
void* storage = (
(boost::python::converter::rvalue_from_python_storage<QString>*)
data)->storage.bytes;
// in-place construct the new QString using the character data
// extraced from the python object
new (storage) QString(value);
// Stash the memory chunk pointer for later use by boost.python
data->convertible = storage;
}
Это что за магия?
Он отдает кусок памяти из некоторой своей кучи, но какого она будет размера (sizeof(QString) ? а как передается это значение?) Потом туда прописывается QString, а сами данные где? QString(value) - здесь сам выделит память?
(http://misspent.wordpress.com/2009/09/27/how-to-write-boost-python-converters/ - вот здесь исходники полностью есть с QString)
Я пока так сделал, чтобы лишний раз память не выделять.
функция ищет первое вхождение байта со старшим битом равным 1.
code:
int get_bytes_in_next_portion3(std::string buf)
{
int i;
int len = buf.length();
for(i=0;i<len;i++)
if ((buf[i] & 128) != 0)
break;
return i;
}
int get_bytes_in_next_portion5(PyObject *py_str)
{
if (!PyString_Check(py_str))
PyErr_SetString(PyExc_RuntimeError, "not str!");
Py_INCREF(py_str);
int len = PyString_GET_SIZE(py_str);
char *ptr = PyString_AS_STRING(py_str);
int i;
//for(i=0;buf[i] != '\0';i++)
for(i=0; i < len ;i++)
if (((ptr[i]) & 128) != 0)
break;
Py_DECREF(py_str);
return i;
}
int get_bytes_in_next_portion4(PyObject *py_str)
{
Py_INCREF(py_str);
int len = PyString_GET_SIZE(py_str);
char *ptr = PyString_AS_STRING(py_str);
for(i=0; i < len ;i++)
if (((ptr[i]) & 128) != 0)
break;
Py_DECREF(py_str);
return i;
}
BOOST_PYTHON_MODULE (_csomemodule)
{
using namespace boost::python;
def("get_bytes_in_next_portion4", get_bytes_in_next_portion4);
}
В ответ на:
[2]done in 125,312,500 nsec // на питоне
[3]done in 2,812,500 nsec // std::string
[4]done in 2,031,250 nsec
[5]done in 1,953,125 nsec // ???? добавили проверку на строку, стала работать быстрее.
[6]done in 4,296,875 nsec
[7]done in 5,078,125 nsec
6,7 - разные мои реализации передачи custom string. сильно хуже получилось, чем std::string.
Почему 5 работает быстрее, чем 4 совсем не понятно. (хотя разница небольшая, скорей всего погрешность просто).