为什么包含枚举的 C++ 方法会在 SWIG/C# 中导致 AccessViolationExceptions?

why are c++ methods containing enums causing AccessViolationExceptions in SWIG/C#?

我正在使用 SWIG 生成本机 32 位 c++ dll 的包装器。 SWIG 生成一个 C++ 包装器文件和许多生成的 C# 代码,这些代码被编译成一个 dll(C++/CLI 和 C# 项目都构建为 x86)并且生成的函数可以通过 C# 调用,除了那些包含枚举的函数。一个例子:

SWIG 生成了 interface_wrap.cxx 文件:

SWIGEXPORT int SWIGSTDCALL CSharp_myMethod(long jarg1, long jarg2, void * jarg3, void * jarg4) {
int jresult ;
long arg1 ;
long arg2 ;
myEnum arg3 ;
double *arg4 = 0 ;
myEnum const *argp3 ;
int result;

arg1 = (long)jarg1; 
arg2 = (long)jarg2; 
argp3 = (myEnum *)jarg3; 
if (!argp3) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "Attempt to dereference null myEnum const", 0);
return 0;
}
arg3 = *argp3; 
arg4 = (double *)jarg4;
if (!arg4) {
SWIG_CSharpSetPendingExceptionArgument(SWIG_CSharpArgumentNullException, "double & type is null", 0);
return 0;
} 
result = (int)myMethod(arg1,arg2,arg3,*arg4);
jresult = result; 
return jresult;
}

C# 外部函数委托定义:

[global::System.Runtime.InteropServices.DllImport("ProjectWrapper", EntryPoint="CSharp_myMethod")]
public static extern int myMethod(int jarg1, int jarg2, [MarshalAs(UnmanagedType.U4)]myEnum jarg3, out double jarg4);

Interface.i 文件提取:

%module ProjectWrapper
%{
#include "myEnumDefinition.h"
%}

%include "enums.swg"

// %typemap(csbase) myEnum "short" // is something like this needed??

%typemap(cstype, out="myEnum") myEnum&, const myEnum& "ref myEnum"
%typemap(cstype, out="myEnum") myEnum, const myEnum "myEnum"
%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.U4)]", outattributes="[return: MarshalAs(UnmanagedType.U4)]", out="myEnum") myEnum&, const myEnum& "ref myEnum"
%typemap(imtype, inattributes="[MarshalAs(UnmanagedType.U4)]", outattributes="[return: MarshalAs(UnmanagedType.U4)]") myEnum, const myEnum "myEnum"
%typemap(csin) myEnum&, const myEnum& "ref $csinput"
%typemap(csin) myEnum, const myEnum "$csinput"

int myMethod(const long start,const long end,const myEnum enumvalue, double& result);

枚举的 C# 定义:

public enum myEnum {
  myEnum_value1,
  myEnum_value2,
  myEnum_value3
}

枚举的 C++ 定义(来自 myEnumDefinition.h)

enum myEnum
{
  myEnum_value1,
  myEnum_value2,
  myEnum_value3
};

当它调用 C# myMethod 外部委托时,它每次都会抛出 AccessViolationException。如果我尝试在没有任何枚举作为参数的情况下调用其他方法,它工作正常。

我不明白这里有什么问题。我尝试以不同的方式 MarshalAs 枚举,但我无法设法避免抛出此异常。生成包装器时,我是否在 SWIG 接口文件中遗漏了什么?

根据这一行,Swig 似乎需要一个指向枚举值的指针:

argp3 = (myEnum *)jarg3;

看起来 C++ 方法在其第三个参数中需要一个 myEnum* 值。所以你应该将你的枚举参数作为 ref:

public static extern int myMethod(int jarg1, int jarg2, ref myEnum jarg3, out double jarg4);