我有一个从已导入 C# 项目的 C++ 库中调用的函数
我认为它要求一个指向数组的指针。但我不知道如何使它工作。
这就是它的要求function(float*, float*);
但如果我做类似的事情
float[] f = {};
float[] f1 = {};
function(f,f1);
它说有无效的论点。
我有一个从已导入 C# 项目的 C++ 库中调用的函数
我认为它要求一个指向数组的指针。但我不知道如何使它工作。
这就是它的要求function(float*, float*);
但如果我做类似的事情
float[] f = {};
float[] f1 = {};
function(f,f1);
它说有无效的论点。
float * 是 C# 中的浮点指针类型。
如果函数需要浮点指针参数 (float *),则必须假定函数在指针上工作,可能涉及指针算术。因此,保留该签名很重要。
要将 C# 中的浮点数组作为浮点指针 (float*) 传递,您需要在不安全的上下文中固定/修复内存中的数组以获取指向它们的指针,您可以将其传递给函数以保留其功能:
unsafe
{
fixed (float* ptr_f = f) //or equivalently "... = &f[0]" address of f[0]
fixed (float* ptr_f2 = f2) //or equivalently "... = &f2[0]" address of f2[0]
{
function( ptr_f, ptr_f2 );
}
}
您还需要将程序集标记为不安全(在项目属性 > 构建选项卡 > 允许不安全代码复选框中)。
如果这是通过导入的方法,DLLImport()
您可以简单地将数组指针替换为类型化数组。
所以一个签名:
[DLLImport("some.dll")]
SomeMethod(int* a, float* b)
变成
[DLLImport("some.dll")]
SomeMethod(int[] a, float[] b)
请注意,这假设原始 c/c++ 方法需要一个数组。如果指针不打算引用数组,这将不起作用。
您需要确切知道调用的 C++ 函数期望什么。
在 C(和 C++)中,所有这些函数签名的所有意图和目的都完全相同:
void foo( float *x , float *y ) ;
void foo( float *x , float y[] ) ;
void foo( float x[] , float *y ) ;
void foo( float x[] , float y[] ) ;
它们都带有 2 个参数,每个参数都包含一个指向(包含地址)类型变量的指针float
。所有这些表达式在 C/C++ 中完全相同:
float x[] ;
float *y ;
float r1 = *(x+37) ; // all evaluate to the zero-relative
float r2 = x[37] ; // 37th element of the array.
float r3 = *(y+37) ;
float r4 = y[37] ;
*x
说:“获取float
位于x
.*(x+n)
,其中n
是一个整数值,表示“获取包含在 x 中的地址,并在其中添加由表达式获得的偏移量(以字节为单位)sizeof(float) * n
。获取float
位于结果地址处的值。x[n]
完全等同于指针表达式*(x+n)
。由于 C/C++ 中的数组没有任何关联的元数据来描述它们的大小,因此您需要确切地知道被调用函数的期望。
通常,传递一个指针(通过引用调用)以允许调用者取消引用该点并为您设置一个值 - 相当于 C#ref
和out
关键字:
float x ;
float y ;
Foo( ref x , ref y ) ; // the callee MAY, but is not REQUIRED to set a value before returning to the caller.
Bar( out x , out y ) ; // the callee MUST set a value before returning to the caller.
您的函数使用的惯用语始终用于定位数组,但通常也会传递一个大小:
void foo( float *array , int array_length ) ;
虽然这并不罕见,但如果函数期望数组是一个非零数值列表,则类似于 C 风格、以 NUL 结尾的字符串。给定函数签名,例如:
float compute_mean( float *Xs ) ;
期望这样调用它并不罕见:
float Xs[] = { 3.0 , 2.5 , 9.8 , 7,5 , 0 , } ;
float mean = compute_mean( Xs ) ;
和定义是这样的:
float compute_mean( float *Xs )
{
float n = 0.0 ;
float sum = 0.0 ;
float mean ;
while ( *p )
{
++n ;
sum += *p++ ;
}
mean = n > 0 ? sum / n : 0.0 ;
return mean ;
}
所以你需要知道你正在调用的方法的语义。
希望这可以帮助。
这在 C# 中根本不起作用,当在 C# 中导入 C/C++ 库时,您应该使用IntPtr
而不是 float*,请参阅此处的一些示例:float* from C to C#
它要求一个浮点指针,(内存中包含 IEEE 浮点值的点的机器地址。)C# 不允许托管使用指针,因此您需要构造一个 IntPtr变量并将其传递给 C++功能。
注意:仅仅因为它被调用IntPtr
并不意味着它只是一个指向整数的指针。Int 是因为所有指针都是整数。它可以是指向任何东西的指针。