我有3个C ++结构以及两个方法,我想通过C#使用它们。这是我的C#代码以及对C ++代码的一些评论。
[StructLayout(LayoutKind.Sequential)]
public unsafe struct smat
{
public long rows;
public long cols;
public long vals;
public long* pointr;
public long* rowind;
public double* value;
};
[StructLayout(LayoutKind.Sequential)]
public unsafe struct dmat {
long rows;
long cols;
double **value;
};
[StructLayout(LayoutKind.Sequential)]
public unsafe struct svdrec {
int d;
dmat Ut; // it was dmat* in C++
double *S;
dmat Vt; // it was dmat* in C++
};
[DllImport(@"file.dll", EntryPoint = "svdNewSMat", CallingConvention = CallingConvention.Cdecl)]
public static extern smat svdNewSMat(int rows, int cols, int vals); // it was smat* in C++
[DllImport(@"file.dll", EntryPoint = "svdLAS2", CallingConvention = CallingConvention.Cdecl)]
public static extern svdrec svdLAS2(smat a, long dimensions, long iterations, double[] las2end, double kappa); // it was smat* and svdrec* in C++
修改 这是C ++标题
typedef struct smat *SMat;
typedef struct dmat *DMat;
typedef struct svdrec *SVDRec;
/* Harwell-Boeing sparse matrix. */
struct smat {
long rows;
long cols;
long vals; /* Total non-zero entries. */
long *pointr; /* For each col (plus 1), index of first non-zero entry. */
long *rowind; /* For each nz entry, the row index. */
double *value; /* For each nz entry, the value. */
};
/* Row-major dense matrix. Rows are consecutive vectors. */
struct dmat {
long rows;
long cols;
double **value; /* Accessed by [row][col]. Free value[0] and value to free.*/
};
struct svdrec {
int d; /* Dimensionality (rank) */
DMat Ut; /* Transpose of left singular vectors. (d by m)
The vectors are the rows of Ut. */
double *S; /* Array of singular values. (length d) */
DMat Vt; /* Transpose of right singular vectors. (d by n)
The vectors are the rows of Vt. */
};
extern DMat svdNewDMat(int rows, int cols);
extern SVDRec svdLAS2(SMat A, long dimensions, long iterations, double end[2],
double kappa);
我没有提供完整的代码,因为它包含了很多库。 以下是我要测试的内容:
var a = svdNewSMat(3, 6, 3);
var m = new double[] {1, 2};
var r = svdLAS2(a, 1, 0, m, 1e-6); // I get the Exception here
第二行让我尝试读取或写入受保护的内存错误。 有任何想法吗?提前谢谢。
答案 0 :(得分:1)
如果是smat *和dmat *,请使用IntPtr而不是smad / dmat。
答案 1 :(得分:1)
如果你正在处理来自DLL的指针,你可以使用IntPtr。请记住,在这项工作中会发生很多装箱/拆箱。
答案 2 :(得分:1)
您不能简单地在C#端用dmat替换dmat *。指针不会自动编组为参考
请查看http://msdn.microsoft.com/en-us/library/0szztey7(v=vs.80).aspx如何正确编组嵌入式指针。
答案 3 :(得分:0)
我不相信c ++模块可以对c#struct执行操作。
尝试使用类而不是结构。
答案 4 :(得分:0)
在函数声明中,等效于指向指针的pinvoke通常是ref IntPtr
在结构声明中(和其他人指出的那样),它应该只是IntPtr
。请记住,在函数调用中,事情通常比仅仅使结构声明正确更复杂(例如,可能需要修改调用约定)。