c++代码可以编译,但是运行时找不到库函数(函数名相差1个字符)



我正在编写一个包装c++库的Python扩展模块。在我的模块中,我在库(代码)中调用函数Rule.set_filter,并且编译,但是当我运行它时,它会与ImportError: dlopen(/Users/larsga/cvs-co/fhdb/reports/pymapnik3.cpython-310-darwin.so, 0x0002): symbol not found in flat namespace一起失败。如你所见,这是在MacOS上。

找不到的符号很长:

__ZN6mapnik4rule10set_filterERKNSt3__110shared_ptrIN6mapbox4util7variantIJNS_10value_nullEbidN6icu_7113UnicodeStringENS_9attributeENS_16global_attributeENS_23geometry_type_attributeENS4_17recursive_wrapperINS_10unary_nodeINS_4tags6negateEEEEENSC_INS_11binary_nodeINSE_4plusEEEEENSC_INSI_INSE_5minusEEEEENSC_INSI_INSE_4multEEEEENSC_INSI_INSE_3divEEEEENSC_INSI_INSE_3modEEEEENSC_INSI_INSE_4lessEEEEENSC_INSI_INSE_10less_equalEEEEENSC_INSI_INSE_7greaterEEEEENSC_INSI_INSE_13greater_equalEEEEENSC_INSI_INSE_8equal_toEEEEENSC_INSI_INSE_12not_equal_toEEEEENSC_INSD_INSE_11logical_notEEEEENSC_INSI_INSE_11logical_andEEEEENSC_INSI_INSE_10logical_orEEEEENSC_INS_16regex_match_nodeEEENSC_INS_18regex_replace_nodeEEENSC_INS_19unary_function_callEEENSC_INS_20binary_function_callEEEEEEEE

Demangled:

_mapnik::rule::set_filter(std::__1::shared_ptr<mapbox::util::variant<mapnik::value_null, bool, int, double, icu_71::UnicodeString, mapnik::attribute, mapnik::global_attribute, mapnik::geometry_type_attribute, mapbox::util::recursive_wrapper<mapnik::unary_node<mapnik::tags::negate> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::plus> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::minus> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::mult> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::div> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::mod> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::less> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::less_equal> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::greater> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::greater_equal> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::equal_to> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::not_equal_to> >, mapbox::util::recursive_wrapper<mapnik::unary_node<mapnik::tags::logical_not> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::logical_and> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::logical_or> >, mapbox::util::recursive_wrapper<mapnik::regex_match_node>, mapbox::util::recursive_wrapper<mapnik::regex_replace_node>, mapbox::util::recursive_wrapper<mapnik::unary_function_call>, mapbox::util::recursive_wrapper<mapnik::binary_function_call> > > const&)

当我查看mapnik的dylib时,我发现在那里定义了一个非常相似的函数:

__ZN6mapnik4rule10set_filterERKNSt3__110shared_ptrIN6mapbox4util7variantIJNS_10value_nullEbxdN6icu_7113UnicodeStringENS_9attributeENS_16global_attributeENS_23geometry_type_attributeENS4_17recursive_wrapperINS_10unary_nodeINS_4tags6negateEEEEENSC_INS_11binary_nodeINSE_4plusEEEEENSC_INSI_INSE_5minusEEEEENSC_INSI_INSE_4multEEEEENSC_INSI_INSE_3divEEEEENSC_INSI_INSE_3modEEEEENSC_INSI_INSE_4lessEEEEENSC_INSI_INSE_10less_equalEEEEENSC_INSI_INSE_7greaterEEEEENSC_INSI_INSE_13greater_equalEEEEENSC_INSI_INSE_8equal_toEEEEENSC_INSI_INSE_12not_equal_toEEEEENSC_INSD_INSE_11logical_notEEEEENSC_INSI_INSE_11logical_andEEEEENSC_INSI_INSE_10logical_orEEEEENSC_INS_16regex_match_nodeEEENSC_INS_18regex_replace_nodeEEENSC_INS_19unary_function_callEEENSC_INS_20binary_function_callEEEEEEEE

Demangled:

_mapnik::rule::set_filter(std::__1::shared_ptr<mapbox::util::variant<mapnik::value_null, bool, long long, double, icu_71::UnicodeString, mapnik::attribute, mapnik::global_attribute, mapnik::geometry_type_attribute, mapbox::util::recursive_wrapper<mapnik::unary_node<mapnik::tags::negate> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::plus> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::minus> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::mult> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::div> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::mod> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::less> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::less_equal> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::greater> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::greater_equal> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::equal_to> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::not_equal_to> >, mapbox::util::recursive_wrapper<mapnik::unary_node<mapnik::tags::logical_not> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::logical_and> >, mapbox::util::recursive_wrapper<mapnik::binary_node<mapnik::tags::logical_or> >, mapbox::util::recursive_wrapper<mapnik::regex_match_node>, mapbox::util::recursive_wrapper<mapnik::regex_replace_node>, mapbox::util::recursive_wrapper<mapnik::unary_function_call>, mapbox::util::recursive_wrapper<mapnik::binary_function_call> > > const&)

这是不一样的,虽然。字符91(基于0)在我的代码中是i,但在mapnik库中是x

不同的是我的库中的10value_nullEbidN6icu和mapnik中的10value_nullEbxdN6icu。参见EbidEbxd

现在,我的问题是为什么这里有一个字符的区别?不知何故,我必须编译这两个代码库略有不同,但我不知道如何。Mapnik是用SConsm构建的,而Python扩展是用distutils构建的。 Mapnik是用make构建的,然后安装在/usr/local/lib/libmapnik.dylib。扩展模块是用python3 setup.py build构建的。我使用DYLD_PRINT_LIBRARIES=YES来验证它正在加载哪个mapnik库。

使用的编译器是clang,如果有帮助的话。

使用@mat的提示,i意味着int,x意味着long long,我能够弄清楚。

set_filter的参数类型是std::shared_ptr<expr_node>。(代码)。expr_node原来是util::variant类型混合了很多类型。这些是在缺失的符号中列出的。

i/x的位置与value_integer在可选类型列表中的位置非常接近。

进一步挖掘,我发现如果没有定义BIGINT,value_integer是32位的,如果定义了,则是64位的。(代码。)

所以我发现mapnik一定是用BIGINT编译的,而我的模块是没有编译的。通过在我的setup.py中添加-DBIGINTextra_compile_args,我能够解决这个问题。(谢谢@mat !)

最新更新