使用来自 c# 的 c++ uint8_t * 使用 SWIG

Posted

技术标签:

【中文标题】使用来自 c# 的 c++ uint8_t * 使用 SWIG【英文标题】:Use c++ uint8_t * from c# using SWIG 【发布时间】:2018-06-04 09:17:00 【问题描述】:

我有一个看起来像这样的函数:

virtual int64_t Read(uint8_t* buffer, int64_t bufferLength) = 0

我们想要覆盖(因为这是一个抽象类)并从 c# 代码实现(使用director)。使用

%include "arrays_csharp.i"
%apply uint8_t INPUT[] uint8_t* buffer

我能够得到一个带有

签名的 c# 翻译
public virtual long Read(byte[] buffer, long bufferLength)

这正是我想要的。但是在尝试编译 SWIG 代码时,我们收到如下错误:

 error C2440: '=': cannot convert from 'void *' to 'unsigned char *'
 note: Conversion from 'void*' to pointer to non-'void' requires an explicit cast

因为生成的 swig cc 文件中有这个 lins:

 int64_t c_result = SwigValueInit< int64_t >() ;
 long long jresult = 0 ;
 unsigned char* jbuffer = 0 ;
 long long jbufferLength  ;
 long long jbufferOffset  ;

 if (!swig_callbackRead__SWIG_0) 
    throw Swig::DirectorPureVirtualException("mip::Stream::Read");
   else 
    jbuffer = (void *) buffer; <========= FAIL LINE
    jbufferLength = bufferLength;
    jresult = (long long) swig_callbackRead__SWIG_0(jbuffer, jbufferLength);
    c_result = (int64_t)jresult; 
  

如何告诉 SWIG 不要转换为 (void *)?

【问题讨论】:

【参考方案1】:

看起来directorin 类型映射不完全正确。我认为这应该足以解决它,在您的 %apply 指令之后:

%typemap(directorin) uint8_t *buffer "$input = $1;"

上面的 typemap 只匹配名为 buffer 的非 const uint8_t* 参数。如果我们愿意,我们可以让它更通用,例如:

%typemap(directorin) SWIGTYPE * "$input = $1;"

将匹配没有更好匹配的任何内容,无论是 const 还是非常量。我无法弄清楚为什么这不是默认设置,所以这里有可能会破坏我没有想到的其他地方的东西,所以你可能更愿意继续在应用它的地方保持选择性..

你也可以这样做:

%typemap(directorin) SWIGTYPE * "$input = ($1_ltype)$1;"

或者添加另一个变体:

%typemap(directorin) const SWIGTYPE * "$input = const_cast<$1_ltype>($1);"

【讨论】:

非常感谢,这对这个基金有用,但我有同样的问题 virtual int64_t Write(const uint8_t* buffer, int64_t bufferLength)= 0 仍然有同样的问题。还有 - 你能解释一下它有什么帮助吗? @AssafSapir 您也可以将其应用于 const 事物:%typemap(directorin) const uint8_t *buffer "$input = $1;",但我也使用更通用的选项编辑了答案。 应用通用方式确实适用于两者,但对于写入功能,它现在抱怨cannot convert from 'const uint8_t *' to 'unsigned char *' @AssafSapir 在 SWIGTYPE 上添加了另外一些变体。如果您使用const SWIGTYPE * 表单,您还需要保留非常量表单。【参考方案2】:

来自编译器的错误信息很简单。您应该将void * 显式转换为unsigned char *

试试:

jresult = (long long) swig_callbackRead__SWIG_0(static_cast<unsigned char *>(jbuffer), jbufferLength);

【讨论】:

但是我如何告诉 SWIG 创建这个? cc 文件由 SWIG 自动生成 @AssafSapir 可以修改生成的cc文件吗?

以上是关于使用来自 c# 的 c++ uint8_t * 使用 SWIG的主要内容,如果未能解决你的问题,请参考以下文章

我想从 C++ 非托管代码调用 C# 委托。无参数委托工作正常,但有参数委托使我的程序崩溃

在 C++ 中从 size_t 转换/转换为 uint8_t?

c++中uint8_t*值的含义和调试(打印)

C# 包装类和来自 c++ 的 dllimport

使用来自 C# 的托管 C++ dll

使用 emscripten 如何将 C++ uint8_t 数组获取到 JS Blob 或 UInt8Array