这是一个已知错误,多年前已在 SWIG org 中报告过,请参阅
https://github.com/swig/swig/issues/283 和
https://github.com/swig/swig/issues/998
此错误在最新版本中尚未修复(直到现在是版本 4.0.2)。
代码的bug在swig\Lib\csharp\std_string.i。有了这个错误,当有字符串回调时,它会在我的应用程序的 C++ 中生成这样的函数:
void SwigDirector_MyCode::LogDebug(std::string const &message) {
char * jmessage = 0 ;
if (!swig_callbackLogDebug) {
throw Swig::DirectorPureVirtualException("SDS::ISDSLogger::LogDebug");
} else {
jmessage = SWIG_csharp_string_callback((&message)->c_str());
swig_callbackLogDebug(jmessage);
}
}
应从 C++ 代码调用 LogDebug。
在代码中,jmessage 是新分配的内存。您可以在调用后更改 jmessage 中的第一个字符来验证它,并且您可以看到 (&message)->c_str() 没有更改。
有想法说应该调用 free() 或 delete 来释放从 SWIG_csharp_string_callback() 创建的内存。
但这对我不起作用。我正在使用 SWIG 从 C++ 生成 C# 包装器。
我的解决方案是在我的项目 .i 文件中为 std::string const & 类型定义新的类型映射。
%typemap(directorin) const std::string & %{ $input = const_cast<char *>($1.c_str()); %}
所以我生成的代码变成了:
void SwigDirector_MyCode::LogDebug(std::string const &message) {
char * jmessage = 0 ;
if (!swig_callbackLogDebug) {
throw Swig::DirectorPureVirtualException("MyCode::LogDebug");
} else {
jmessage = const_cast<char *>((&message)->c_str());
swig_callbackLogDebug(jmessage);
}
}
在此代码中,不再分配 jmessage。
它已经在 Debian 9 mono 和 Windows 7 与 VS2017 上进行了测试。