为什么包含枚举的 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);
我正在使用 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);