Возврат структуры C в Python с помощью pybind11

#python #c #pybind11

Вопрос:

У меня возникла проблема с вызовом простой процедуры C с использованием pybind11. У меня есть функция, которая создает, инициализирует и возвращает структуру. В C это работает нормально. При вызове из Python он не инициализируется должным образом. Есть идеи, что случилось?

вывод из C (test_testlib.cpp):

 head_status.head_num =  1
 

вывод из Python 3.7 (test_testlib.py):

 $ python test_pybind.py
head_num=-858993460
head_num=2
 

Код:

тестлиб.ч:

 #pragma once

#ifdef TESTLIB_EXPORTS
#define TESTLIB_API extern "C" __declspec(dllexport)
#else
#define TESTLIB_API extern "C" __declspec(dllimport)
#endif

struct HeadStatus {
    const int getHeadNum() { return head_num; };
    void setHeadNum(const int new_head_num) { head_num =  new_head_num; };
    int head_num;
};

TESTLIB_API HeadStatus amp;get_head_status();
 

testlib.cpp:

 #include "pch.h"
#include "framework.h"
#include "testlib.h"

#include <pybind11/pybind11.h>
namespace py = pybind11;

#include <iostream>

TESTLIB_API HeadStatus amp;get_head_status()
{
    HeadStatus head_status = HeadStatus();
    head_status.head_num = 1;
    return head_status;
}

using namespace pybind11::literals;   // needed for _a style arguments in m.def

PYBIND11_MODULE(testlib, m) {
    m.doc() = "pybind11 example plugin"; // optional module docstring

    py::class_<HeadStatus>(m, "HeadStatus")
        .def("getHeadNum", amp;HeadStatus::getHeadNum)
        .def("setHeadNum", amp;HeadStatus::setHeadNum);

    m.def("get_head_status", amp;get_head_status, "A function that returns a struct for the status of a head");
}
 

test_testlib.cpp:

 #include <iostream>
#include "../testlib/testlib.h"

int main()
{
    HeadStatus hs = get_head_status();
    std::cout << "head_status.head_num =  " << hs.head_num << "n";
}
 

test_testlib.py:

 import testlib

head_status = testlib.get_head_status()
head_num = head_status.getHeadNum()
print(f"head_num={head_num}")  # prints -858993460

head_status.setHeadNum(2)
head_num = head_status.getHeadNum()
print(f"head_num={head_num}")  # prints 2
 

Комментарии:

1. get_head_status() возвращает ссылку на локальную переменную. В C это не «работает нормально», это просто происходит случайно.