【问题标题】:allocVector() in C and System.AccessViolationException: Attempted to read or write protected memory?C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?
【发布时间】:2015-06-06 19:43:36
【问题描述】:

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

【问题讨论】:

    标签: c# c++ c r


    【解决方案1】:

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

    退后一步,我为您的 C#/C 互操作提出几点建议:

    • 如果您在此 API 中没有很多自己的现有 C 代码,我建议您将其移植到 C# 并使用 R.NET(NuGet packagesource code
    • 如果你确实有大量的 C/C++ 代码,或者绝对需要 C 层,你可以看看这个sample code。在回答之前,我把它放在一起测试了几件事,所以我不妨提交源代码。

    为了其他读者,从问题中的功能阐述的症结是:

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

    【讨论】:

    • 感谢您的回答。我遵循了在您的代码中使用 rClr 的方法,但是在编译时遇到了以下错误:
    • 错误 LNK1104: 无法打开文件 'Rdll.lib' C:\Users\Stephan\Documents\GitHub\rdotnet-support\wrapcppdll\mycpp\LINK mycpp
    • 在站点 codeplex 上调用它们以在我的系统上构建 rClr 时,我按照以下步骤操作: %R% CMD check rClr %R% CMD REMOVE rClr %R% CMD INSTALL rClr 我收到了消息构建成功。
    • 但我不知道为什么我总是收到错误消息:无法打开文件 'Rdll.lib' 我还有一个关于 R.NET 的问题:是否可以通过某些特定的方法调用 R 的函数包,例如“rrcov”?如果您向我推荐一些材料,我将不胜感激。提前致谢,
    猜你喜欢
    • 2012-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多