我撰寫了一個 C 庫來從電子設計自動化 (EDA) 工具中提取仿真資料(= 帶有 (x,y) 或 (x,y,z) 分量的簡單向量)。更具體地說,這些資料代表不同時間點的電信號。
C 庫提供了多種方法。兩個重要的是:
std::vector<std::string> getSignalNames() // Returns all signal names in the file
std::vector<std::vector<double>> getSignals() // Returns the actual data as M x N matrix (with M rows and N columns)
在 C 中使用庫可以完美地作業并產生預期的結果,例如:
getSignalNames():
Signal1
Signal2
getSignals():
1 1 1 2
2 1 2 3
Perl 程式員要求我也向他們提供庫,我決定使用包裝器生成器 SWIG來創建系結。我完成了本教程,并且能夠成功設定一個最小的作業示例。
根據示例,我為 C 庫撰寫了一個完整的 SWIG 介面檔案。包裝器生成和構建程序運行順利,我也可以getSignalNames()毫無問題地使用:
// Perl snippet to read out signal names
my $parserPointer = new waveformparser::ScopeParser("input.file");
$signalNames = $parserPointer->getSignalNames();
foreach my $signalName ( @$signalNames ) {
print "$signalName\n";
}
// Output:
Signal1
Signal2
但是,我在使用以下的回傳值時遇到了麻煩getSignals():
// Perl snippet to read out the actual signal data
my $parserPointer = new waveformparser::ScopeParser("input.file");
$signalData = $parserPointer->getSignals();
foreach my $rowAsHashRef ( @$signalData ) {
print "reftype: " . reftype($rowAsHashRef) . "\n";
print "keys: " . keys(%$rowAsHashRef) . "\n"
}
// Output:
reftype: HASH
keys: 0
reftype: HASH
keys: 0
如您所見,每一行在 Perl 中都表示為散列,但散列中沒有鍵。然而,當使用Perl 的 Data::Dumper 時,我可以看到每一行的正確資料型別:
my $parserPointer = new waveformparser::ScopeParser("input.file");
$signalData = $parserPointer->getSignals();
print Dumper $signalData;
// Output:
$VAR1 = [
bless( {}, 'waveformparser::vector_1d_double' ),
bless( {}, 'waveformparser::vector_1d_double' )
];
即,根據資料轉儲器,每一行由幾列(即,'waveformparser::vector_1d_double')組成,這些列在 SWIG 介面檔案中定義如下:
...
%include "std_vector.i"
%template(vector_1d_double) std::vector<double>;
%template(vector_2d_double) std::vector<std::vector<double>>;
...
我現在的問題是:如何vector_1d_double在 Perl 中訪問這個“祝福”(包裝)物件的元素?
我想,SWIG 會為這些物件提供方便的訪問方法。即,底層的 C 資料型別只是一個簡單的雙精度一維向量 ( std::vector<double>)。
uj5u.com熱心網友回復:
您需要撰寫一個輸出型別映射std::vector<std::vector<double>>以轉換為正確的 Perl 陣列陣列。下面是一個例子:
VecVec.i :
%module VecVec
%typemap(out) std::vector<std::vector<double>> {
AV *array = (AV *) newAV();
auto vec_ptr = &$1;
std::vector<std::vector<double>>& vec = *vec_ptr;
for (const auto &item : vec) {
AV *subarray = (AV *) newAV();
for (const auto &subitem : item) {
av_push(subarray, newSVnv((NV) subitem));
}
av_push(array, (SV*) newRV_noinc((SV*)subarray));
}
$result = newRV_noinc((SV*) array);
sv_2mortal($result);
argvi ;
}
%{
#include "VecVec.h"
%}
%include "VecVec.h"
VecVec.h :
#ifndef VEVEC_H_
#define VECVEC_H_
#include <vector>
class VecVec
{
public:
VecVec() {}
~VecVec() {}
std::vector<std::vector<double>> getSignals();
private:
};
#endif
VecVec.cpp :
#include <string>
#include <vector>
#include <iostream>
#include "VecVec.h"
std::vector<std::vector<double>> VecVec::getSignals()
{
std::vector<std::vector<double>> vec {
{1, 2, 3},
{4, 5, 6}
};
return vec;
}
然后編譯:
perl_include_dir=$(perl -MConfig -e'print $Config{archlib}')"/CORE"
swig -perl5 -c -I/usr/include VecVec.i
g -fPIC -c VecVec.cpp
g -I${perl_include_dir} -c -fPIC -g -o VecVec_wrap.o VecVec_wrap.cxx
g -shared -L. VecVec.o VecVec_wrap.o -o VecVec.so
并使用test.pl測驗模塊:
use strict;
use warnings;
use Data::Dumper qw(Dumper);
use lib '.';
use VecVec;
my $p = VecVec::VecVec->new();
my $sig = $p->getSignals();
print Dumper($sig);
輸出:
$VAR1 = [
[
'1',
'2',
'3'
],
[
'4',
'5',
'6'
]
];
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/378823.html
上一篇:引數值是多少
下一篇:我無法將任何值存盤在陣列@AA中
