C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?
Posted
技术标签:
【中文标题】C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?【英文标题】:allocVector() in C and System.AccessViolationException: Attempted to read or write protected memory? 【发布时间】: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
【问题讨论】:
【参考方案1】:快速阅读,我认为您使用值 6 作为指针的值。里面还有其他问题。
退后一步,我为您的 C#/C 互操作提出几点建议:
如果您在此 API 中没有很多自己的现有 C 代码,我建议您将其移植到 C# 并使用 R.NET(NuGet package、source 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”?如果您向我推荐一些材料,我将不胜感激。提前致谢,以上是关于C 和 System.AccessViolationException 中的 allocVector():试图读取或写入受保护的内存?的主要内容,如果未能解决你的问题,请参考以下文章