从 c# 调用另一个 dll 中定义的 c++ dll 中的函数
Calling functions in a c++ dll from c# that are defined in another dll
我已经能够读取包含如下方法的 c++ dll 中的函数:
extern "C" { __declspec(dllexport) Vector4 resta(Vector4 vector1,Vector4 vector2); }
我得到了一个实现以下功能的 dll:
extern "C"{ __declspec(dllexport) void pinverse(Vector4 skel[20], Vector4 result[20]); }
此函数采用 20 个 vector4 变量的数组,并使用犰狳例程计算矩阵的伪逆,但我没有被告知具体是哪些例程,当从 c# 执行该函数时,我得到一个全为零的矩阵。我还执行了 c++ 中的函数,同时将犰狳 dll 保存在 projecto 文件夹中并将它们添加到链接器输入中,我得到了一个非零的结果。所以问题是,我如何包含应该在 c# 代码上执行的犰狳例程?如果 dll 中的例程没有从库中找到其他例程,为什么我没有看到任何错误消息?
我使用的c#语法是这样的:
[DllImport("C:\Users\PALMA\Documents\Visual Studio 2013\Projects\PruebaTest\PruebaTest\PruebaDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void pinverse(Vector4[] skel, Vector4[] result);
而 Vector4 是这样定义的结构:
public struct Vector4{
public static bool operator !=(Vector4 vector1, Vector4 vector2);
public static bool operator ==(Vector4 vector1, Vector4 vector2);
public float W { get; set; }
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public override bool Equals(object obj);
public bool Equals(Vector4 vector);
public override int GetHashCode();
}
然后在 c# 中我继续创建一个 class 来调用导入的函数,如下所示:
public static Vector4[] ProbarArmadillo(Vector4[] resultado)
{
Vector4[] skel1=new Vector4[20];
Vector4[] skel2=new Vector4[20];
skel1[0].X = (float)-0.505401; skel1[0].Y = (float)-0.0968128; skel1[0].Z = (float)2.54701; skel1[0].W = 1;
skel1[1].X = (float)-0.547074; skel1[1].Y = (float)-0.0348387; skel1[1].Z = (float)2.5876; skel1[1].W = 1;
skel1[2].X = (float)-0.532013; skel1[2].Y = (float)0.323909; skel1[2].Z = (float)2.60893; skel1[2].W = 1;
skel1[3].X = (float)-0.468823; skel1[3].Y = (float)0.514958; skel1[3].Z = (float)2.63824; skel1[3].W = 1;
skel1[4].X = (float)-0.642778; skel1[4].Y = (float)0.221897; skel1[4].Z = (float)2.49321; skel1[4].W = 1;
skel1[5].X = (float)-0.765644; skel1[5].Y = (float)0.172945; skel1[5].Z = (float)2.27342; skel1[5].W = 1;
skel1[6].X = (float)-0.793357; skel1[6].Y = (float)0.258069; skel1[6].Z = (float)2.04539; skel1[6].W = 1;
skel1[7].X = (float)-0.802389; skel1[7].Y = (float)0.291529; skel1[7].Z = (float)2.01768; skel1[7].W = 1;
skel1[8].X = (float)-0.405216; skel1[8].Y = (float)0.194607; skel1[8].Z = (float)2.75541; skel1[8].W = 1;
skel1[9].X = (float)-0.297749; skel1[9].Y = (float)0.153036; skel1[9].Z = (float)2.85184; skel1[9].W = 1;
skel1[10].X = (float)-0.164521; skel1[10].Y = (float)0.228597; skel1[10].Z = (float)2.93223; skel1[10].W = 1;
skel1[11].X = (float)-0.105644; skel1[11].Y = (float)0.269457; skel1[11].Z = (float)2.98627; skel1[11].W = 1;
skel1[12].X = (float)-0.551655; skel1[12].Y = (float)-0.15617; skel1[12].Z = (float)2.48071; skel1[12].W = 1;
skel1[13].X = (float)-0.605082; skel1[13].Y = (float)-0.55405; skel1[13].Z = (float)2.37626; skel1[13].W = 1;
skel1[14].X = (float)-0.659974; skel1[14].Y = (float)-0.880765; skel1[14].Z = (float)2.35654; skel1[14].W = 1;
skel1[15].X = (float)-0.597098; skel1[15].Y = (float)-0.914582; skel1[15].Z = (float)2.29637; skel1[15].W = 1;
skel1[16].X = (float)-0.448527; skel1[16].Y = (float)-0.184062; skel1[16].Z = (float)2.58483; skel1[16].W = 1;
skel1[17].X = (float)-0.49097; skel1[17].Y = (float)-0.628932; skel1[17].Z = (float)2.57352; skel1[17].W = 1;
skel1[18].X = (float)-0.515788; skel1[18].Y = (float)-0.962651; skel1[18].Z = (float)2.54876; skel1[18].W = 1;
skel1[19].X = (float)-0.476598; skel1[19].Y = (float)-1.02878; skel1[19].Z = (float)2.53682; skel1[19].W = 1;
skel2[0].X = (float)-0.505401; skel2[0].Y = (float)-0.0968128; skel2[0].Z = (float)2.54701; skel2[0].W = 1;
skel2[1].X = (float)-0.547074; skel2[1].Y = (float)-0.0348387; skel2[1].Z = (float)2.5876; skel2[1].W = 1;
skel2[2].X = (float)-0.532013; skel2[2].Y = (float)0.323909; skel2[2].Z = (float)2.60893; skel2[2].W = 1;
skel2[3].X = (float)-0.468823; skel2[3].Y = (float)0.514958; skel2[3].Z = (float)2.63824; skel2[3].W = 1;
skel2[4].X = (float)-0.642778; skel2[4].Y = (float)0.221897; skel2[4].Z = (float)2.49321; skel2[4].W = 1;
skel2[5].X = (float)-0.765644; skel2[5].Y = (float)0.172945; skel2[5].Z = (float)2.27342; skel2[5].W = 1;
skel2[6].X = (float)-0.793357; skel2[6].Y = (float)0.258069; skel2[6].Z = (float)2.04539; skel2[6].W = 1;
skel2[7].X = (float)-0.802389; skel2[7].Y = (float)0.291529; skel2[7].Z = (float)2.01768; skel2[7].W = 1;
skel2[8].X = (float)-0.405216; skel2[8].Y = (float)0.194607; skel2[8].Z = (float)2.75541; skel2[8].W = 1;
skel2[9].X = (float)-0.297749; skel2[9].Y = (float)0.153036; skel2[9].Z = (float)2.85184; skel2[9].W = 1;
skel2[10].X = (float)-0.164521; skel2[10].Y = (float)0.228597; skel2[10].Z = (float)2.93223; skel2[10].W = 1;
skel2[11].X = (float)-0.105644; skel2[11].Y = (float)0.269457; skel2[11].Z = (float)2.98627; skel2[11].W = 1;
skel2[12].X = (float)-0.551655; skel2[12].Y = (float)-0.15617; skel2[12].Z = (float)2.48071; skel2[12].W = 1;
skel2[13].X = (float)-0.605082; skel2[13].Y = (float)-0.55405; skel2[13].Z = (float)2.37626; skel2[13].W = 1;
skel2[14].X = (float)-0.659974; skel2[14].Y = (float)-0.880765; skel2[14].Z = (float)2.35654; skel2[14].W = 1;
skel2[15].X = (float)-0.597098; skel2[15].Y = (float)-0.914582; skel2[15].Z = (float)2.29637; skel2[15].W = 1;
skel2[16].X = (float)-0.448527; skel2[16].Y = (float)-0.184062; skel2[16].Z = (float)2.58483; skel2[16].W = 1;
skel2[17].X = (float)-0.49097; skel2[17].Y = (float)-0.628932; skel2[17].Z = (float)2.57352; skel2[17].W = 1;
skel2[18].X = (float)-0.515788; skel2[18].Y = (float)-0.962651; skel2[18].Z = (float)2.54876; skel2[18].W = 1;
skel2[19].X = (float)-0.476598; skel2[19].Y = (float)-1.02878; skel2[19].Z = (float)2.53682; skel2[19].W = 1;
// pinverse(skel1, Resultado);
pinverse(skel1, resultado);
return resultado;
}
最后我像这样在 main 中使用函数:
Vector4[] resultado = new Vector4[20];
resultado= Procesar.ProbarArmadillo(resultado);
Recorder.SaveArmadillo(resultado);
记录器 class 将输出放在 txt 文件中,但该文件显示一个全为零的矩阵。
我认为你的结构声明有点不对劲。我不确定编组器如何处理自动实现的属性。我会避开他们。我会有这样的结构:
[StructLayout(LayoutKind.Sequential)]
public struct Vector4
{
public float W;
public float X;
public float Y;
public float Z;
}
并且p/invoke应该提供方向属性。也不需要 unsafe
我假设你是在随机尝试时添加的。
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern void pinverse(
[In, MarshalAs(UnmanagedType.LPArray, SizeConst = 20)]
Vector4[] skel,
[Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 20)]
Vector4[] result
);
我终于让它工作了。我像这样重写了 c++ 函数:
void inversa(Vector4 *skel1, Vector4 *result){
fmat temp(20, 4);
for (int i = 0; i < 20; i++){
temp(i, 0) = (skel1 + i)->x; temp(i, 1) = (skel1 + i)->y; temp(i, 2) = (skel1 + i)->z; temp(i, 3) = (skel1 + i)->w;
}
fmat B = pinv(temp);
for (int j = 0; j < 20; j++){
(result + j)->x = B(0, j); (result + j)->y = B(1, j); (result + j)->z = B(2, j); (result + j)->w = B(3, j);
}
}
然后像这样编译成一个dll工程:
namespace pdll
{
extern "C"{ __declspec(dllexport) void mensaje(); }
extern "C"{ __declspec(dllexport) void promedio(Vector4 skel1[20], Vector4 skel2[20], Vector4 prom[20]); }
extern "C"{ __declspec(dllexport) void pinverse(Vector4 skel[20], Vector4 result[20]); }
extern "C"{ __declspec(dllexport) void inversa(Vector4 *skel1, Vector4 *result); }
}
并像这样在 c# 中导入它:
[DllImport("C:\Users\PALMA\Documents\Visual Studio 2010\Projects\LeerDLL\PruebaDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void inversa(Vector4* skel1, Vector4* result);
然后像这样创建了一种包装函数:
public static unsafe Vector4[] Inverse(Vector4[] esqueleto, Vector4[] matrizinversa) {
fixed (Vector4* skeletonpointer = esqueleto, inversepointer = matrizinversa)
{
inversa(skeletonpointer,inversepointer);
}
return matrizinversa;
}
并像这样使用它:
Vector4[] resultado = new Vector4[20];
resultado= Procesar.ProbarArmadillo(resultado);
Recorder.SaveArmadillo(resultado);
.txt 文件的输出是:
我唯一尝试过的是通过引用将参数传递给函数,这是从批评按值传递的 Hans Passant 那里得到的想法。
希望这对尝试使用 c# 中的犰狳例程的任何人有所帮助。
我已经能够读取包含如下方法的 c++ dll 中的函数:
extern "C" { __declspec(dllexport) Vector4 resta(Vector4 vector1,Vector4 vector2); }
我得到了一个实现以下功能的 dll:
extern "C"{ __declspec(dllexport) void pinverse(Vector4 skel[20], Vector4 result[20]); }
此函数采用 20 个 vector4 变量的数组,并使用犰狳例程计算矩阵的伪逆,但我没有被告知具体是哪些例程,当从 c# 执行该函数时,我得到一个全为零的矩阵。我还执行了 c++ 中的函数,同时将犰狳 dll 保存在 projecto 文件夹中并将它们添加到链接器输入中,我得到了一个非零的结果。所以问题是,我如何包含应该在 c# 代码上执行的犰狳例程?如果 dll 中的例程没有从库中找到其他例程,为什么我没有看到任何错误消息?
我使用的c#语法是这样的:
[DllImport("C:\Users\PALMA\Documents\Visual Studio 2013\Projects\PruebaTest\PruebaTest\PruebaDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void pinverse(Vector4[] skel, Vector4[] result);
而 Vector4 是这样定义的结构:
public struct Vector4{
public static bool operator !=(Vector4 vector1, Vector4 vector2);
public static bool operator ==(Vector4 vector1, Vector4 vector2);
public float W { get; set; }
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public override bool Equals(object obj);
public bool Equals(Vector4 vector);
public override int GetHashCode();
}
然后在 c# 中我继续创建一个 class 来调用导入的函数,如下所示:
public static Vector4[] ProbarArmadillo(Vector4[] resultado)
{
Vector4[] skel1=new Vector4[20];
Vector4[] skel2=new Vector4[20];
skel1[0].X = (float)-0.505401; skel1[0].Y = (float)-0.0968128; skel1[0].Z = (float)2.54701; skel1[0].W = 1;
skel1[1].X = (float)-0.547074; skel1[1].Y = (float)-0.0348387; skel1[1].Z = (float)2.5876; skel1[1].W = 1;
skel1[2].X = (float)-0.532013; skel1[2].Y = (float)0.323909; skel1[2].Z = (float)2.60893; skel1[2].W = 1;
skel1[3].X = (float)-0.468823; skel1[3].Y = (float)0.514958; skel1[3].Z = (float)2.63824; skel1[3].W = 1;
skel1[4].X = (float)-0.642778; skel1[4].Y = (float)0.221897; skel1[4].Z = (float)2.49321; skel1[4].W = 1;
skel1[5].X = (float)-0.765644; skel1[5].Y = (float)0.172945; skel1[5].Z = (float)2.27342; skel1[5].W = 1;
skel1[6].X = (float)-0.793357; skel1[6].Y = (float)0.258069; skel1[6].Z = (float)2.04539; skel1[6].W = 1;
skel1[7].X = (float)-0.802389; skel1[7].Y = (float)0.291529; skel1[7].Z = (float)2.01768; skel1[7].W = 1;
skel1[8].X = (float)-0.405216; skel1[8].Y = (float)0.194607; skel1[8].Z = (float)2.75541; skel1[8].W = 1;
skel1[9].X = (float)-0.297749; skel1[9].Y = (float)0.153036; skel1[9].Z = (float)2.85184; skel1[9].W = 1;
skel1[10].X = (float)-0.164521; skel1[10].Y = (float)0.228597; skel1[10].Z = (float)2.93223; skel1[10].W = 1;
skel1[11].X = (float)-0.105644; skel1[11].Y = (float)0.269457; skel1[11].Z = (float)2.98627; skel1[11].W = 1;
skel1[12].X = (float)-0.551655; skel1[12].Y = (float)-0.15617; skel1[12].Z = (float)2.48071; skel1[12].W = 1;
skel1[13].X = (float)-0.605082; skel1[13].Y = (float)-0.55405; skel1[13].Z = (float)2.37626; skel1[13].W = 1;
skel1[14].X = (float)-0.659974; skel1[14].Y = (float)-0.880765; skel1[14].Z = (float)2.35654; skel1[14].W = 1;
skel1[15].X = (float)-0.597098; skel1[15].Y = (float)-0.914582; skel1[15].Z = (float)2.29637; skel1[15].W = 1;
skel1[16].X = (float)-0.448527; skel1[16].Y = (float)-0.184062; skel1[16].Z = (float)2.58483; skel1[16].W = 1;
skel1[17].X = (float)-0.49097; skel1[17].Y = (float)-0.628932; skel1[17].Z = (float)2.57352; skel1[17].W = 1;
skel1[18].X = (float)-0.515788; skel1[18].Y = (float)-0.962651; skel1[18].Z = (float)2.54876; skel1[18].W = 1;
skel1[19].X = (float)-0.476598; skel1[19].Y = (float)-1.02878; skel1[19].Z = (float)2.53682; skel1[19].W = 1;
skel2[0].X = (float)-0.505401; skel2[0].Y = (float)-0.0968128; skel2[0].Z = (float)2.54701; skel2[0].W = 1;
skel2[1].X = (float)-0.547074; skel2[1].Y = (float)-0.0348387; skel2[1].Z = (float)2.5876; skel2[1].W = 1;
skel2[2].X = (float)-0.532013; skel2[2].Y = (float)0.323909; skel2[2].Z = (float)2.60893; skel2[2].W = 1;
skel2[3].X = (float)-0.468823; skel2[3].Y = (float)0.514958; skel2[3].Z = (float)2.63824; skel2[3].W = 1;
skel2[4].X = (float)-0.642778; skel2[4].Y = (float)0.221897; skel2[4].Z = (float)2.49321; skel2[4].W = 1;
skel2[5].X = (float)-0.765644; skel2[5].Y = (float)0.172945; skel2[5].Z = (float)2.27342; skel2[5].W = 1;
skel2[6].X = (float)-0.793357; skel2[6].Y = (float)0.258069; skel2[6].Z = (float)2.04539; skel2[6].W = 1;
skel2[7].X = (float)-0.802389; skel2[7].Y = (float)0.291529; skel2[7].Z = (float)2.01768; skel2[7].W = 1;
skel2[8].X = (float)-0.405216; skel2[8].Y = (float)0.194607; skel2[8].Z = (float)2.75541; skel2[8].W = 1;
skel2[9].X = (float)-0.297749; skel2[9].Y = (float)0.153036; skel2[9].Z = (float)2.85184; skel2[9].W = 1;
skel2[10].X = (float)-0.164521; skel2[10].Y = (float)0.228597; skel2[10].Z = (float)2.93223; skel2[10].W = 1;
skel2[11].X = (float)-0.105644; skel2[11].Y = (float)0.269457; skel2[11].Z = (float)2.98627; skel2[11].W = 1;
skel2[12].X = (float)-0.551655; skel2[12].Y = (float)-0.15617; skel2[12].Z = (float)2.48071; skel2[12].W = 1;
skel2[13].X = (float)-0.605082; skel2[13].Y = (float)-0.55405; skel2[13].Z = (float)2.37626; skel2[13].W = 1;
skel2[14].X = (float)-0.659974; skel2[14].Y = (float)-0.880765; skel2[14].Z = (float)2.35654; skel2[14].W = 1;
skel2[15].X = (float)-0.597098; skel2[15].Y = (float)-0.914582; skel2[15].Z = (float)2.29637; skel2[15].W = 1;
skel2[16].X = (float)-0.448527; skel2[16].Y = (float)-0.184062; skel2[16].Z = (float)2.58483; skel2[16].W = 1;
skel2[17].X = (float)-0.49097; skel2[17].Y = (float)-0.628932; skel2[17].Z = (float)2.57352; skel2[17].W = 1;
skel2[18].X = (float)-0.515788; skel2[18].Y = (float)-0.962651; skel2[18].Z = (float)2.54876; skel2[18].W = 1;
skel2[19].X = (float)-0.476598; skel2[19].Y = (float)-1.02878; skel2[19].Z = (float)2.53682; skel2[19].W = 1;
// pinverse(skel1, Resultado);
pinverse(skel1, resultado);
return resultado;
}
最后我像这样在 main 中使用函数:
Vector4[] resultado = new Vector4[20];
resultado= Procesar.ProbarArmadillo(resultado);
Recorder.SaveArmadillo(resultado);
记录器 class 将输出放在 txt 文件中,但该文件显示一个全为零的矩阵。
我认为你的结构声明有点不对劲。我不确定编组器如何处理自动实现的属性。我会避开他们。我会有这样的结构:
[StructLayout(LayoutKind.Sequential)]
public struct Vector4
{
public float W;
public float X;
public float Y;
public float Z;
}
并且p/invoke应该提供方向属性。也不需要 unsafe
我假设你是在随机尝试时添加的。
[DllImport(dllname, CallingConvention = CallingConvention.Cdecl)]
public static extern void pinverse(
[In, MarshalAs(UnmanagedType.LPArray, SizeConst = 20)]
Vector4[] skel,
[Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 20)]
Vector4[] result
);
我终于让它工作了。我像这样重写了 c++ 函数:
void inversa(Vector4 *skel1, Vector4 *result){
fmat temp(20, 4);
for (int i = 0; i < 20; i++){
temp(i, 0) = (skel1 + i)->x; temp(i, 1) = (skel1 + i)->y; temp(i, 2) = (skel1 + i)->z; temp(i, 3) = (skel1 + i)->w;
}
fmat B = pinv(temp);
for (int j = 0; j < 20; j++){
(result + j)->x = B(0, j); (result + j)->y = B(1, j); (result + j)->z = B(2, j); (result + j)->w = B(3, j);
}
}
然后像这样编译成一个dll工程:
namespace pdll
{
extern "C"{ __declspec(dllexport) void mensaje(); }
extern "C"{ __declspec(dllexport) void promedio(Vector4 skel1[20], Vector4 skel2[20], Vector4 prom[20]); }
extern "C"{ __declspec(dllexport) void pinverse(Vector4 skel[20], Vector4 result[20]); }
extern "C"{ __declspec(dllexport) void inversa(Vector4 *skel1, Vector4 *result); }
}
并像这样在 c# 中导入它:
[DllImport("C:\Users\PALMA\Documents\Visual Studio 2010\Projects\LeerDLL\PruebaDll.dll", CallingConvention = CallingConvention.Cdecl)]
public static unsafe extern void inversa(Vector4* skel1, Vector4* result);
然后像这样创建了一种包装函数:
public static unsafe Vector4[] Inverse(Vector4[] esqueleto, Vector4[] matrizinversa) {
fixed (Vector4* skeletonpointer = esqueleto, inversepointer = matrizinversa)
{
inversa(skeletonpointer,inversepointer);
}
return matrizinversa;
}
并像这样使用它:
Vector4[] resultado = new Vector4[20];
resultado= Procesar.ProbarArmadillo(resultado);
Recorder.SaveArmadillo(resultado);
.txt 文件的输出是:
我唯一尝试过的是通过引用将参数传递给函数,这是从批评按值传递的 Hans Passant 那里得到的想法。
希望这对尝试使用 c# 中的犰狳例程的任何人有所帮助。