@@ -333,9 +333,11 @@ typedef struct messageType;
333333 } else {
334334 npy_intp dims[1] = {static_cast<npy_intp>(N)};
335335 $result = PyArray_SimpleNew(1, dims, npyTypeNum);
336- for (size_t recordIndex = 0; recordIndex < N; ++recordIndex ) {
337- void* ptr = PyArray_GETPTR1((PyArrayObject*)$result, recordIndex);
338- *reinterpret_cast<fieldType*>(ptr) = $1->record().at(recordIndex). ## fieldName;
336+ if (!$result) SWIG_fail;
337+
338+ for (size_t i = 0; i < N; ++i ) {
339+ void* ptr = PyArray_GETPTR1((PyArrayObject*)$result, i);
340+ *reinterpret_cast<fieldType*>(ptr) = $1->record().at(i). ## fieldName;
339341 }
340342 }
341343 if (PyErr_Occurred()) SWIG_fail;
@@ -355,27 +357,29 @@ typedef struct messageType;
355357
356358%enddef
357359
358- %define RECORDER_PROPERTY_NUMERIC_1(payloadType, fieldName, fieldType, npyTypeNum, dim1)
359- /*
360- * Exposes a fixed-size 1D numeric array field (e.g. float[3]) as a NumPy array with shape [N, dim1].
361- * Uses contiguous memcpy per record for efficiency.
362- */
360+ %define RECORDER_PROPERTY_NUMERIC_1(payloadType, fieldName, fieldType, npyTypeNum)
363361%typemap(out) Recorder<payloadType>* Recorder<payloadType>::_ ## fieldName ## _array
364362{
365363 size_t N = $1->record().size();
366364 if (N == 0) {
367365 npy_intp dims[1] = {0};
368366 $result = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
369367 } else {
370- npy_intp dims[2] = {static_cast<npy_intp>(N), (npy_intp) dim1};
368+ /* Derive dimensions from compiled type */
369+ auto &first = $1->record().at(0).fieldName;
370+ const size_t d1 = sizeof(first) / sizeof(first[0]);
371+ const size_t elemsPerRecord = d1;
372+ const size_t bytesPerRecord = elemsPerRecord * sizeof(fieldType);
373+
374+ npy_intp dims[2] = {static_cast<npy_intp>(N), (npy_intp) d1};
371375 $result = PyArray_SimpleNew(2, dims, npyTypeNum);
376+ if (!$result) SWIG_fail;
372377
373378 fieldType* dest = static_cast<fieldType*>(PyArray_DATA((PyArrayObject*)$result));
374- size_t recordStride = dim1;
375379
376- for (size_t recordIndex = 0; recordIndex < N; ++recordIndex ) {
377- const fieldType* src = &($1->record().at(recordIndex ).fieldName[0]);
378- std::memcpy(dest + recordIndex * recordStride , src, recordStride * sizeof(fieldType) );
380+ for (size_t i = 0; i < N; ++i ) {
381+ const fieldType* src = &($1->record().at(i ).fieldName[0]);
382+ std::memcpy(dest + i * elemsPerRecord , src, bytesPerRecord );
379383 }
380384 }
381385 if (PyErr_Occurred()) SWIG_fail;
@@ -395,29 +399,34 @@ typedef struct messageType;
395399
396400%enddef
397401
398- %define RECORDER_PROPERTY_NUMERIC_2(payloadType, fieldName, fieldType, npyTypeNum, dim1, dim2)
399- /*
400- * Exposes a fixed-size 2D numeric array field (e.g. float[3][3]) as a NumPy array with shape [N, dim1, dim2].
401- */
402+ %define RECORDER_PROPERTY_NUMERIC_2(payloadType, fieldName, fieldType, npyTypeNum)
402403%typemap(out) Recorder<payloadType>* Recorder<payloadType>::_ ## fieldName ## _array
403404{
404405 size_t N = $1->record().size();
405406 if (N == 0) {
406407 npy_intp dims[1] = {0};
407408 $result = PyArray_SimpleNew(1, dims, NPY_FLOAT64);
408409 } else {
409- npy_intp dims[3] = {static_cast<npy_intp>(N), (npy_intp) dim1, (npy_intp) dim2};
410+ /* Derive dimensions from compiled type */
411+ auto &first = $1->record().at(0).fieldName;
412+ const size_t d1 = sizeof(first) / sizeof(first[0]);
413+ const size_t d2 = sizeof(first[0]) / sizeof(first[0][0]);
414+ const size_t elemsPerRecord = d1 * d2;
415+ const size_t bytesPerRecord = elemsPerRecord * sizeof(fieldType);
416+
417+ npy_intp dims[3] = {static_cast<npy_intp>(N), (npy_intp) d1, (npy_intp) d2};
410418 $result = PyArray_SimpleNew(3, dims, npyTypeNum);
419+ if (!$result) SWIG_fail;
411420
412421 fieldType* dest = static_cast<fieldType*>(PyArray_DATA((PyArrayObject*)$result));
413- size_t recordStride = dim1 * dim2;
414422
415- for (size_t recordIndex = 0; recordIndex < N; ++recordIndex ) {
416- const fieldType* src = &($1->record().at(recordIndex ).fieldName[0][0]);
417- std::memcpy(dest + recordIndex * recordStride , src, recordStride * sizeof(fieldType) );
423+ for (size_t i = 0; i < N; ++i ) {
424+ const fieldType* src = &($1->record().at(i ).fieldName[0][0]);
425+ std::memcpy(dest + i * elemsPerRecord , src, bytesPerRecord );
418426 }
427+
428+ if (PyErr_Occurred()) SWIG_fail;
419429 }
420- if (PyErr_Occurred()) SWIG_fail;
421430}
422431
423432%extend Recorder<payloadType> {
0 commit comments