我正在尝试包装 glmnet 库(http://cran.r-project.org/web/packages/glmnet/index.html),以便我可以在 C# 中解决模型稀疏的一般线性模型。然而,原始函数有大约 20 个参数,所以我开始(对于 Fortran 来说是全新的)用一个很小的子例程来测试如何传递数据。不幸的是,我总是得到一个 AccessViolationException。
这是代码:
Fortran 子例程。我使用 Rtools 附带的 gfortran 编译器(http://cran.r-project.org/bin/windows/Rtools/),使用 -m64 选项将它编译成 dll(是的,64 位是必需的,因为我处理得很好大块数据)。是的,使用 i 可能会导致越界......但这只是为了测试。
subroutine testaaa (f,i,fa,ia)
real fa(i)
integer ia(i)
ia(1) = 1337
ia(i) = 666
fa(1) = 8.15
fa(i) = 333
end subroutine testaaa
C# PInvoke 代码:
[DllImport("ftest.dll", EntryPoint = "testaaa_", CallingConvention = CallingConvention.StdCall)]
public static extern void Test(
[MarshalAs(UnmanagedType.R4)] float f,
[MarshalAs(UnmanagedType.I4)] int i,
IntPtr fa,
IntPtr ia);
这就是它的名称:
var fa = new float[4];
var ia = new int[4];
IntPtr faPtr = Marshal.AllocHGlobal(fa.Length * sizeof(float));
Marshal.Copy(fa, 0, faPtr, fa.Length);
IntPtr iaPtr = Marshal.AllocHGlobal(ia.Length * sizeof(float));
Marshal.Copy(ia, 0, iaPtr, ia.Length);
GlmnetDllWrapper.Test(0.4f, 4,faPtr,iaPtr);
我还尝试直接传递数组并赋予它们 [MarshalAs(UnmanagedType.LPArray)] 属性。没有什么对我有用。
你有什么建议从哪里开始或改变什么?
更新 1:即使只传递 float 和 int 已经导致异常:
subroutine testbbb (f,i)
i = 815
f = 8.15
return
end subroutine testbbb
C# Pinvoke 和 call 相应更改。我究竟做错了什么?