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
快速阅读,我认为你使用值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;
}