对于我的某个Perl项目,我需要几个Perl进程来共享一些位于C ++库中的资源。 (不要问,这不是这个问题的核心,只是背景。)
因此,我试图在这个上下文中钻研两个“新”字段:IPC::Shareable
,并使用SWIG包装C ++。看来我在那里做错了,这就是我想问的问题。
在C ++方面,我编写了一个小型测试类Rectangle
,其中包含一个空构造函数,一个set
和一个size
成员函数。
然后我将该类包装在SWIG生成的Perl包example
中。
在Perl方面,我试过SWIG模块按预期工作:
use example;
my $testrec = new example::Rectangle;
$testrec->set( 6, 7 );
print $testrec->size() . "\n";
这样可以打印“42”。
然后我尝试使用IPC::Shareable
测试我的方式。我编写了两个Perl脚本,一个“服务器”和一个“客户端”来测试资源共享。
“服务器”:
use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 'yes', exclusive => 0, mode => 0644, destroy => 'yes' );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect, 'IPC::Shareable', 'g_rect', { %options } or die;
$v_array = [ "0" ];
$v_rect = new example::Rectangle;
$v_rect->set( 6, 7 );
while ( 1 ) {
print "server array: " . join( " - ", @$v_array ) . "\n";
print "server rect: " . $v_rect->size() . "\n";
sleep 3;
}
“客户”:
use IPC::Shareable;
use example;
# v_ for variable, g_ for (IPC) glue
my $v_array;
my $v_rect;
my %options = ( create => 0, exclusive => 0, mode => 0644, destroy => 0 );
tie $v_array, 'IPC::Shareable', 'g_array', { %options } or die;
tie $v_rect, 'IPC::Shareable', 'g_rect', { %options } or die;
my $count = 0;
while ( 1 ) {
print "client array: " . join( " - ", @$v_array ) . "\n";
print "client rect: " . $v_rect->size() . "\n";
push( @$v_array, ++$count );
$v_rect->set( 3, $count );
sleep 3;
}
首先启动“服务器”,然后启动“客户端”,我得到“服务器”的输出:
server array: 0
server rect: 42
server array: 0 - 1
server rect: 42
server array: 0 - 1 - 2
server rect: 42
这个输出为“客户端”:
client array: 0
client rect: 0
client array: 0 - 1
client rect: 3
client array: 0 - 1 - 2
client rect: 6
显然,数组引用可以共享,但是客户端没有“看到”服务器的示例:: Rectangle,而是在一个(零初始化的)流氓内存上工作,而后者依次是服务器什么都不知道...
我怀疑我必须对$v_rect
做一些事情以使其正常工作,但我在OO Perl中不够坚实,不知道是什么。有人救人吗?
答案 0 :(得分:3)
你要做的事情是行不通的。你将不得不咬紧牙关并做一些形式的消息传递。
我不太清楚SWIG如何为Perl包装C(++)级别的对象,但它很可能是通常的,在整数槽中可怕的“指针”策略。在此设置中,它将分配一个C(++)对象并在Perl标量中存储指向它的指针。 Perl对象将成为这个标量的祝福参考。当对Perl对象的所有引用都消失时,Perl类的析构函数将显式释放C(++)对象。一种更现代的技术就像XS :: Object :: Magic模块允许你做的那样。
但是包装器的细节甚至都不重要。重要的是对象是不透明到Perl!通过联系,IPC :: Shareable无论如何都使用了一些时尚和坦率的脆弱技术。它可能适用于您的Perl对象,也可能不适用。但是当您共享Perl对象时,C(++)对象将 NOT 被共享。怎么可能呢? Perl对此一无所知。它不可能。
您应该做的是在消息传递和序列化方面考虑问题。为了序列化你的C(++)对象,你需要允许来自C方面的一些合作。看看Storable模块为序列化对象提供的钩子。就消息传递/排队而言,我很高兴使用ZeroMQ,它为您提供了一个简单的类似套接字的接口。