boost.python避免两次注册内部类,但仍然在python中公开(boost.python Avoid registering inner class twice but still expose in python)
我有一些C ++数据结构,其中模板化的外部结构具有内部结构。 根据模板参数,内部结构可能是也可能不是同一类型。 当我使用boost.python将结构暴露给python时,我希望能够将内部类称为Outer.Inner。 在我的boost.python暴露代码中,我应该只暴露每个不同的内部类型一次。 我可以查询boost.python注册表以避免多次暴露同一个内部类,但我该怎么做才能使以前暴露的内部类成为其外部类的属性? 考虑到这个被剥离的例子,问题可能会更清楚:
#include <boost/python.hpp> struct inner { }; template< typename T > struct outer { typedef inner inner_t; static const char * name(); static void expose() { using namespace boost::python; class_< outer< T > > outer_class( name() ); // check if inner type is in registry already const type_info inner_info = boost::python::type_id< inner_t >(); const converter::registration * inner_registration = boost::python::converter::registry::query( inner_info ); if( inner_registration == 0 || inner_registration->m_to_python == 0 ) { // not already in registry scope outer_scope( outer_class ); class_< inner_t > inner_class( "Inner" ); } else { // already in registry because exposed via different outer // what to put here? In python we need Outer.Inner to exist } } }; template<> const char * outer< int >::name() { return "IntOuter"; } template<> const char * outer< double >::name() { return "DoubleOuter"; } BOOST_PYTHON_MODULE( inner_classes ) { outer< int >::expose(); outer< double >::expose(); }
这是我想要运行的python代码:
import inner_classes as IC IC.IntOuter.Inner IC.DoubleOuter.Inner
为了完整性,这里有一个Jamroot来编译上面的内容:
import python ; use-project boost : $(BOOST_ROOT) ; project : requirements <library>/boost/python//boost_python ; python-extension inner_classes : inner-classes.cpp ; install install : inner_classes : <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION <location>. ; local rule run-test ( test-name : sources + ) { import testing ; testing.make-test run-pyd : $(sources) : : $(test-name) ; } run-test test : inner_classes test_inner_classes.py ;
I have some C++ data structures where a templated outer struct has an internal struct. Depending on the template parameter the internal structs may or may not be the same type. When I expose the structures to python using boost.python I want to be able to refer to the inner classes as Outer.Inner. In my boost.python exposing code I should only expose each distinct inner type once. I can query the boost.python registry to avoid exposing the same inner class more than once but what should I do to make a previously exposed inner class an attribute of its outer class? The question might be clearer given this stripped down example:
#include <boost/python.hpp> struct inner { }; template< typename T > struct outer { typedef inner inner_t; static const char * name(); static void expose() { using namespace boost::python; class_< outer< T > > outer_class( name() ); // check if inner type is in registry already const type_info inner_info = boost::python::type_id< inner_t >(); const converter::registration * inner_registration = boost::python::converter::registry::query( inner_info ); if( inner_registration == 0 || inner_registration->m_to_python == 0 ) { // not already in registry scope outer_scope( outer_class ); class_< inner_t > inner_class( "Inner" ); } else { // already in registry because exposed via different outer // what to put here? In python we need Outer.Inner to exist } } }; template<> const char * outer< int >::name() { return "IntOuter"; } template<> const char * outer< double >::name() { return "DoubleOuter"; } BOOST_PYTHON_MODULE( inner_classes ) { outer< int >::expose(); outer< double >::expose(); }
Here's the python code that I would like to run:
import inner_classes as IC IC.IntOuter.Inner IC.DoubleOuter.Inner
For completeness here's a Jamroot to compile the above:
import python ; use-project boost : $(BOOST_ROOT) ; project : requirements <library>/boost/python//boost_python ; python-extension inner_classes : inner-classes.cpp ; install install : inner_classes : <install-dependencies>on <install-type>SHARED_LIB <install-type>PYTHON_EXTENSION <location>. ; local rule run-test ( test-name : sources + ) { import testing ; testing.make-test run-pyd : $(sources) : : $(test-name) ; } run-test test : inner_classes test_inner_classes.py ;
原文:https://stackoverflow.com/questions/16892966
最满意答案
一些例子来理解结构。 这些都意味着相同(差异很小):
# just a hash %hash = ( 'a', 1, 'b', '2' ); %hash = ( a => 1, b => '2' ); # ref to hash $hash_ref = \%hash; $hash_ref = { a => 1, b => 2 }; print $hash{ a }; #prints 1 print $hash_ref->{ a }; #prints 1
1和'2'是值。 价值观可能只是标量。 对SOMETHING的引用也是标量。 上例中的$ hash_ref。
在您的示例中,您说第一个哈希是列表。 我认为你的意思是数组:
$list = [ $error1, $error2 ]; $error1 = { error_name => $description } $description = { status => 'status', message => 'msg', params => [ 1,2,'asdf'] }
你知道一个子获取标量列表。 如果要将哈希传递给sub,则只需传递对此哈希的引用
fn( \%hash );
并在sub获取此哈希:
sub fn { my( $hash ) = @_; print $hash->{ key_name }; }
我想你只有一个错误列表,每个错误包含键:
$list_of_errors = [ { status => 1, message => 'hello' }, { status => 2, message => 'hello2' }, { status => 1, message => 'hello3' }, ] fn( $list_of_errors ); sub fn { my( $le ) = @_; print $le->[1]{ message }; #will print 'hello2' # print $le->{ error_name }{ status }; #try this in case hash of hashes }
要更好地理解结构,请尝试使用Data :: Dump模块;
use Data::Dump qw/ pp /; %hash = ( a => 1 ); $hash = \%hash; $arr = [ 1, 2, 'a' ]; print pp $hash, \%hash, $arr;
祝你好运。
码
our %error = ( ERROR_1 => { statusCode => 561, message => "an unexpected error occurred at location X", params => $param_1, }, ERROR_2 => { statusCode => 561, message => "an unexpected error occurred at location Y", params => $param_1, } ); sub print_err { my( $err_name ) = @_; print $error{ $err_name }{ message } ."\n"; } print_err( 'ERROR_1' ); print_err( 'ERROR_2' );
Some examples to understand structures. These all mean same (with small difference):
# just a hash %hash = ( 'a', 1, 'b', '2' ); %hash = ( a => 1, b => '2' ); # ref to hash $hash_ref = \%hash; $hash_ref = { a => 1, b => 2 }; print $hash{ a }; #prints 1 print $hash_ref->{ a }; #prints 1
1 and '2' are values. Values maybe only scalars. Reference to SOMETHING is also scalar. $hash_ref in the example above.
In your example you say 1st hash is list. I think you mean array:
$list = [ $error1, $error2 ]; $error1 = { error_name => $description } $description = { status => 'status', message => 'msg', params => [ 1,2,'asdf'] }
You know that a sub get list of scalars. If you want to pass hash into sub you just pass reference to this hash
fn( \%hash );
and get this hash at sub:
sub fn { my( $hash ) = @_; print $hash->{ key_name }; }
I suppose you have just a list of errors, each of them contain keys:
$list_of_errors = [ { status => 1, message => 'hello' }, { status => 2, message => 'hello2' }, { status => 1, message => 'hello3' }, ] fn( $list_of_errors ); sub fn { my( $le ) = @_; print $le->[1]{ message }; #will print 'hello2' # print $le->{ error_name }{ status }; #try this in case hash of hashes }
To understand structures better try to use Data::Dump module;
use Data::Dump qw/ pp /; %hash = ( a => 1 ); $hash = \%hash; $arr = [ 1, 2, 'a' ]; print pp $hash, \%hash, $arr;
Good luck.
CODE
our %error = ( ERROR_1 => { statusCode => 561, message => "an unexpected error occurred at location X", params => $param_1, }, ERROR_2 => { statusCode => 561, message => "an unexpected error occurred at location Y", params => $param_1, } ); sub print_err { my( $err_name ) = @_; print $error{ $err_name }{ message } ."\n"; } print_err( 'ERROR_1' ); print_err( 'ERROR_2' );
相关问答
更多-
TCP/IP模型是一个________。[2023-05-19]
a -
Perl Hash比较(Perl Hash Comparison)[2022-03-17]
假设您要比较值 ,比如开始位置,这是我的方法: use warnings; use strict; open my $in, '<', '1.txt' or die "$!\n"; open my $in2, '<', '2.txt' or die "$!\n"; my (%hash1, %hash2); while (<$in>){ chomp; next unless /^\s+/; my ($key, $start, $stop) = /\s+(\d+)\s+(\d+) ... -
下列中不属于面向对象的编程语言的是?[2022-05-30]
a -
一些例子来理解结构。 这些都意味着相同(差异很小): # just a hash %hash = ( 'a', 1, 'b', '2' ); %hash = ( a => 1, b => '2' ); # ref to hash $hash_ref = \%hash; $hash_ref = { a => 1, b => 2 }; print $hash{ a }; #prints 1 print $hash_ref->{ a }; #prints 1 1和'2'是值。 价值观可能只是标量。 对SOME ...
-
$xcHash->{XC_HASH_LINES}是一个arrayref而不是一个数组。 所以 $xcHash->{XC_HASH_LINES} = (); 应该: $xcHash->{XC_HASH_LINES} = []; foreach需要一个列表。 它可以是一个包含单个标量( foreach ($foo) )的列表,但这不是你想要的。 foreach $xcLine ($xcHash->{XC_HASH_LINES}) 应该: foreach my $xcLine (@{$xcHash->{XC ...
-
在Perl中访问哈希哈希值(Accessing hash of hashes in Perl)[2021-11-07]
您没有正确传递哈希值,因为子例程期望哈希引用,并且您传入的哈希值将扩展为键和值列表。 这就是为什么它试图使用“style”作为hashref,因为它是它传递的第一个键。 只需更改对此的调用即可。 $self->applyStyle(\%options); You're not passing in the hash correctly as the subroutine is expecting a hash ref and you're passing in a hash which will be e ... -
不要在参考上调用密钥。 在实际散列上调用它。 另外,这个$test{$a}->应该是$test->{$a} ,因为$test是一个哈希引用。 foreach (sort { $test->{$a}{'value1'} <=> $test->{$b}{'value1'} } keys %{$test} ){ print "key: $_ value: $test->{$_}->{'value1'}\n" } 如果你use strict; 并use warnings; 打开,你会得到以下错误提醒你一个 ...
-
哈希的哈尔哈希(Perl Hash of Hashes)[2021-12-21]
for my $family ( keys %HoH ) { if ($HoH{$family}->{checked}) { # Do what you want... } } for my $family ( keys %HoH ) { if ($HoH{$family}->{checked}) { # Do what you want... } } -
假设你的数组看起来像这样: my @keys = qw/a b c a a/; my @values = qw/1 2 3 4 1/; 它就像一个简单的for循环一样简单: for ($i = 0; $i < scalar @keys; $i++) { $hash{$keys[$i]}{$values[$i]} += 1; } 然后,您可以使用嵌套循环迭代内部值(计数): foreach my $key (keys %hash) { while (my ($value, $count ...
-
使用List :: Util(它是core perl的一部分)中的reduce函数。 #!/usr/bin/perl use strict; use warnings; use List::Util qw/reduce/; my %hash = ( "a" => { "b" => 2, "c" => 1, }, "d" => { "e" => 4, }, ); my $key = 'a'; print "For key: ...