Perl: IPC :: Shareable object and SWIG'ed C ++ disagree

For a specific Perl project, I need several Perl processes to share some resources located in the C ++ library. (Do not ask, this is not the core of this question, but only the context.)

Thus, I am trying to delve into two “new” fields in this context: IPC::Shareable and C ++ wrapping with SWIG. It seems that I am doing something wrong, and I would like to ask about this.


On the C ++ side, I wrote a small Rectangle test class with an empty constructor, set and size functions.

Then I wrapped the class in the Perl package created by the SWIG example .

On the Perl side, I tried if the SWIG module works as expected:

 use example; my $testrec = new example::Rectangle; $testrec->set( 6, 7 ); print $testrec->size() . "\n"; 

This prints "42", as it should be.

Then I tried to test my way of using IPC::Shareable . I wrote two Perl scripts, one “server” and one “client”, to test resource sharing.

"Server":

 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; } 

"Customer":

 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; } 

Starting with “server” and then “client”, I get this output for “server”:

 server array: 0 server rect: 42 server array: 0 - 1 server rect: 42 server array: 0 - 1 - 2 server rect: 42 

And this conclusion is for the "client":

 client array: 0 client rect: 0 client array: 0 - 1 client rect: 3 client array: 0 - 1 - 2 client rect: 6 

Thus, the array reference is shared, but the client does not "see" the :: Rectangle server example, but works on the (zero initialization) part of the rogue memory, which, in turn, the server knows nothing about ...

I have a suspicion that I must do something with $v_rect to make this work properly, but I'm not sure enough about OO Perl to find out what. Anyone to help?

+4
source share
1 answer

What you are trying to do will not work. You will have to bite the bullet and do some form of messaging.

I don’t quite remember exactly how SWIG wraps C (++) level objects for Perl, but this is most likely the usual admittedly awful integer-slot pointer strategy. In this setting, it will highlight the C (++) object and save a pointer to it in the Perl scanner. The Perl object will be a blessed reference to this scalar. The C (++) object will be explicitly freed by the Perl class destructor when all references to the Perl object disappear. A more modern technique for this would be something like what the XS :: Object :: Magic module allows.

But wrapper details are not so important. The important thing is that the object is opaque to Perl! For communications, IPC :: Shareable in any case uses non-standard and frankly fragile technology. It may or may not work well for your Perl objects. But when you share the Perl object, the C (++) object will be separated by NOT . How could this be? Perl knows nothing about this. And this is not possible.

Instead, you should think about the problem in terms of message passing and serialization. To serialize C (++) objects, you will want to allow some collaboration from C. Look at the hooks that the Storable module provides for serializing objects. As for messaging / queuing, I liked working with ZeroMQ, which gives you a simple socket interface.

+2
source

All Articles