代码之家  ›  专栏  ›  技术社区  ›  SWilliams

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

  •  3
  • SWilliams  · 技术社区  · 11 年前

    我正在使用SWIG生成一个本地32位c++dll的包装器。SWIG生成一个C++包装文件和大量生成的C#代码,这些代码被编译成一个dll(C++/CLI和构建为x86的C#项目),生成的函数可以通过C#fine调用,但包含enum的函数除外。例如:

    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);
    

    接口.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。如果我尝试在没有任何enum作为参数的情况下调用其他方法,它会正常工作。

    我不明白这里出了什么问题。我已经试过了 MarshalAs 枚举的方式不同,但我无法避免引发此异常。在生成包装器时,我是否缺少SWIG接口文件中的某些内容?

    1 回复  |  直到 11 年前
        1
  •  1
  •   The Vermilion Wizard    11 年前

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

    argp3 = (myEnum *)jarg3;
    

    看起来C++方法需要 myEnum* 值。因此,您可能应该将enum参数作为ref传递:

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