我将C ++应用程序移植到C#并遇到一些指针问题。
我想要实现的是传递带有偏移量的数组指针,以便传递的函数可以在数组的正确部分上工作。我不想更改函数的签名以为偏移量添加额外的值。
所以,这是我想用C#传递的C ++代码示例:
void DoSomething( double p[] )
{
p[0] = 0.4;
p[1] = 0.4;
}
int main()
{
double Vector[3];
Vector[0] = 0.2;
Vector[1] = 0.2;
Vector[2] = 0.2;
DoSomething( &Vector[1] );
}
我怎么能这样做?请记住,我无法通过偏移?
[编辑] 谢谢大家的答案。 首先,我要道歉:复制代码时犯了一个大错误。
我写了
DoSomething( Vector[1] );
在最后一行而不是
DoSomething( &Vector[1] );
这已得到纠正。
然后我意识到我对签名不是很清楚。我可以略微更改函数的签名,但我无法添加任何参数
我已经在使用"不安全"和#34;固定"关键字,所以它不会伤害我
它不需要是高效的代码,因为这个移植是一个快速的&由其他人为原型项目编写的算法的脏实现。如果项目是" Ok go",代码将被抛出垃圾并在C ++ dll中重写。
功能" DoSomething"实际上它是一些其他函数的嵌套,它被设计为一个快速的数学工作但遗憾的是,我不具备自己编写代码的所有知识。这就是为什么我认为作者已经很好地设计了它的功能,因为它在世界范围内被广泛使用。
我会尝试使用Servy的建议,并在我回来的几天内回复你。
答案 0 :(得分:1)
在不改变DoSomething
的签名的情况下不可能,但是你可以避免需要传递两个数组并且它在整个地方并排偏移。您可以通过创建一个组成数组的类来跟踪偏移量来实现:
public class ArrayReference<T> : IEnumerable<T>
{
//you can keep these entirely private if you prefer
public T[] Array { get; private set; }
public int Offset { get; private set; }
public ArrayReference(T[] array, int offset)
{
Array = array;
Offset = offset;
}
public T this[int index]
{
get
{
return Array[index + Offset];
}
set
{
Array[index + Offset] = value;
}
}
public int Length
{
get
{
return Array.Length - Offset;
}
}
public IEnumerator<T> GetEnumerator()
{
for (int i = Offset; i < Array.Length; i++)
yield return Array[i];
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public static ArrayReference<T> operator +(
ArrayReference<T> reference, int offset)
{
return new ArrayReference<T>(reference.Array, reference.Offset + offset);
}
public static ArrayReference<T> operator -(
ArrayReference<T> reference, int offset)
{
return new ArrayReference<T>(reference.Array, reference.Offset - offset);
}
public static implicit operator ArrayReference<T>(T[] array)
{
return new ArrayReference<T>(array, 0);
}
public static implicit operator T[](ArrayReference<T> reference)
{
return reference.ToArray();
}
}
您可能希望根据您的特定需求为此添加其他功能。您可以根据需要或希望公开底层数组的功能。
答案 1 :(得分:-1)
这实际上不是你在C#中的方式。
执行此操作的唯一方法是使用不安全的代码,即使这样也不是一个好的实现,因为您的方法不安全,并且您的数组必须是fixed
。
fixed
关键字会阻止您的数组被垃圾收集器移动到内存中的其他位置,但它可能会导致内存分区,从而导致性能下降。
此外,即使按设计这也不是一件好事,因为你不知道你方法中的数组边界。
但如果你真的想这样做,请选择调查员。
在您的主要方法中:
double[] d = new double[3];
d[0] = 1.0;
d[1] = 2.0;
d[2] = 3.0;
IEnumerator<double> e = d.AsEnumerable().GetEnumerator();
e.MoveNext();
tryEnumerate(e);
然后是您的DoSomething
方法:
static void DoSomething(IEnumerator<double> e)
{
while(e.MoveNext())
Console.WriteLine(e.Current.ToString());
}
答案 2 :(得分:-1)
最好的解决方案是从c ++代码构建一个dll,这样我就可以在C#中使用该函数而无需修改签名。
在C#项目中使用dll:
using System.Runtime.InteropServices;
namespace MyDLL
{
public class TestLib
{
[DllImport( "name_of_your_dll" )]
public static extern DoSomething( double p[] );
}
}
答案 3 :(得分:-3)
更新代码以使用扩展方法显示链接。您可以轻松返回任何和所有更改并更新所需的任何内容。
List<double> Vector;
Vector.Add(0.2);
Vector.Add(0.2);
Vector.Add(0.2);
DoSomething(Vector.GetRange(index,count));
如果您需要维护原始列表,请执行以下操作:
public static List<double> GetRange(static List<double> list, int index, int count){
return list.GetRange(Index,Count);
}
public static List<double> DoSomething(static List<double> list){
//do something here
}
像这样使用:
OriginalList().GetRange(Index,Count).DoSomething();