allocVector()在C和System中.AccessViolationException:试图读写受保护的内存

本文关键字:读写 受保护 内存 AccessViolationException System allocVector | 更新日期: 2023-09-27 17:54:02

我有一个问题与allocVector()函数。我用C写了一个可以在r中调用的代码(DLL),我想在c#中调用该DLL的一个方法。DLL代码工作良好,但当编译器到达下一行ROut = allocVector(INTSXP, 2*3)它给出了以下例外:未处理异常:System。AccessViolationException:试图读写受保护的内存。代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <R.h>
#include <Rinternals.h>
#include <Rmath.h>
#include <R_ext/Applic.h>
#include <R_ext/Lapack.h>
#include <Rdefines.h>
#ifdef __cplusplus
extern "C" {
#endif
    void castType(int *result)
    {
        SEXP ROut;
        ROut = allocVector(INTSXP, 2*3)
        ROut = PROTECT(ROut);
        int *clustOut = INTEGER(ROut); 
        result= clustOut ; 
    } 
#ifdef __cplusplus
}
#endif

allocVector()在C和System中.AccessViolationException:试图读写受保护的内存

快速阅读,我认为你使用值6作为指针的值。里面还有其他问题

退一步说,我为你的c#/C互操作提出了一些建议:

    如果你在这个API中没有很多自己的现有C代码,我建议你将它移植到c#并使用rnet (NuGet包,源代码)如果你确实有大量的C/c++代码,或者绝对需要一个C层,你可以看看这个示例代码。在回答之前,我把它放在一起测试了一些事情,所以我不妨提交源代码。

为了方便其他读者,从问题中的功能出发,详细阐述的关键是:

C API:

void c_api_call(int * result)
{
    SEXP p = some_R_calculations();
    int* int_ptr = INTEGER_POINTER(p);
    int n = length(p);
    for (int i = 0; i < n; i++)
        result[i] = int_ptr[i];
    // We are done with p; irrespective of where some_R_calculations got it, 
    // we can notify the R GC that this function releases it.
    R_ReleaseObject(p);
}

c#互操作包装器:

public class CppInterop : DynamicInterop.UnmanagedDll // http://www.nuget.org/packages/DynamicInterop/
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    private delegate void _c_api_call([In, Out] [MarshalAs(UnmanagedType.LPArray)] int[] values);
    public int[] CreateArray()
    {
        // These two following references could be cached for efficiency later on.
        var getLength = this.GetFunction<_c_api_call_getlength>("c_api_call_getlength");
        var getValues = this.GetFunction<_c_api_call>("c_api_call");
        // As far as I know it is preferable, if not needed, to handle arrays in two steps:
        // we need to know the expected length to allocate in C# buffer memory.
        int expectedLength = getLength();
        int[] result = new int[expectedLength];
        getValues(result);
        return result;
    }