11#include " perf_event_array.h"
22#include " core/bpf_exception.h"
3+ #include " core/bpf_map.h"
34
4- PerfEventArray::PerfEventArray (int map_fd , int page_cnt, py::function callback ,
5- py::object lost_callback)
6- : pb_(nullptr ), callback_(std::move(callback)),
5+ PerfEventArray::PerfEventArray (std::shared_ptr<BpfMap> map , int page_cnt,
6+ py::function callback, py::object lost_callback)
7+ : map_(map), pb_(nullptr ), callback_(std::move(callback)),
78 lost_callback_(lost_callback) {
89
10+ if (map->get_type () != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
11+ throw BpfException (" Map '" + map->get_name () +
12+ " ' is not a PERF_EVENT_ARRAY" );
13+ }
14+
915 if (page_cnt <= 0 || (page_cnt & (page_cnt - 1 )) != 0 ) {
1016 throw BpfException (" page_cnt must be a positive power of 2" );
1117 }
@@ -14,7 +20,7 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
1420 pb_opts.sz = sizeof (pb_opts); // Required for forward compatibility
1521
1622 pb_ = perf_buffer__new (
17- map_fd , page_cnt,
23+ map-> get_fd () , page_cnt,
1824 sample_callback_wrapper, // sample_cb
1925 lost_callback.is_none () ? nullptr : lost_callback_wrapper, // lost_cb
2026 this , // ctx
@@ -27,14 +33,33 @@ PerfEventArray::PerfEventArray(int map_fd, int page_cnt, py::function callback,
2733 }
2834}
2935
36+ PerfEventArray::PerfEventArray (std::shared_ptr<BpfMap> map, int page_cnt,
37+ py::function callback,
38+ const std::string &struct_name,
39+ py::object lost_callback)
40+ : PerfEventArray(map, page_cnt, callback, lost_callback) {
41+
42+ auto parent = map->get_parent ();
43+ if (!parent) {
44+ throw BpfException (" Parent BpfObject has been destroyed" );
45+ }
46+
47+ parser_ = parent->get_struct_parser ();
48+ struct_name_ = struct_name;
49+
50+ if (!parser_) {
51+ throw BpfException (" No struct definitions available" );
52+ }
53+ }
54+
3055PerfEventArray::~PerfEventArray () {
3156 if (pb_) {
3257 perf_buffer__free (pb_);
3358 }
3459}
3560
3661void PerfEventArray::sample_callback_wrapper (void *ctx, int cpu, void *data,
37- unsigned int size) {
62+ unsigned int size) {
3863 auto *self = static_cast <PerfEventArray *>(ctx);
3964
4065 // Acquire GIL for Python calls
@@ -44,15 +69,23 @@ void PerfEventArray::sample_callback_wrapper(void *ctx, int cpu, void *data,
4469 // Convert data to Python bytes
4570 py::bytes py_data (static_cast <const char *>(data), size);
4671
47- // Call Python callback: callback(cpu, data, size)
48- self->callback_ (cpu, py_data, size);
72+ if (self->parser_ && !self->struct_name_ .empty ()) {
73+ py::object event = self->parser_ ->parse (self->struct_name_ , py_data);
74+ self->callback_ (cpu, event);
75+ } else {
76+ self->callback_ (cpu, py_data);
77+ }
78+
4979 } catch (const py::error_already_set &e) {
5080 PyErr_Print ();
81+ } catch (const std::exception &e) {
82+ py::gil_scoped_acquire acquire;
83+ py::print (" C++ error in perf callback:" , e.what ());
5184 }
5285}
5386
5487void PerfEventArray::lost_callback_wrapper (void *ctx, int cpu,
55- unsigned long long cnt) {
88+ unsigned long long cnt) {
5689 auto *self = static_cast <PerfEventArray *>(ctx);
5790
5891 if (self->lost_callback_ .is_none ()) {
0 commit comments