c#结构参考以防止复制
我需要在类中有一个私有结构成员,并且正在寻找一种方法来访问该结构成员,而不执行复制 原因是该结构被用作c dll的接口c#结构参考以防止复制,c#,struct,copy,ref,C#,Struct,Copy,Ref,我需要在类中有一个私有结构成员,并且正在寻找一种方法来访问该结构成员,而不执行复制 原因是该结构被用作c dll的接口 public class MyCDllApi { // Marshalled struct [StructLayout(LayoutKind.Sequential)] public struct DllData { [MarshalAs(UnmanagedType.U1)] public byte data1; [
public class MyCDllApi
{
// Marshalled struct
[StructLayout(LayoutKind.Sequential)]
public struct DllData
{
[MarshalAs(UnmanagedType.U1)] public byte data1;
[MarshalAs(UnmanagedType.U1)] public byte data2;
// ...
// lots more; this is really a LARGE struct
}
// DLL Function call
[DllImport("MyC.dll", CallingConvention=CallingConvention.Cdecl)]
private static extern int do_some_work(ref DllData data);
public void doSomeWork()
{
do_some_work(ref m_dllData);
}
public DllData getData();
private DllData m_dllData;
}
public class MyProg
{
static void Main(String args[])
{
MyC_DllApi m_dllApi = new MyCDllApi();
m_dllApi.doSomeWork();
DllData data = m_dllApi.getData();
// Use data
}
}
我想我可以将结构装箱并从getData()返回一个对象,但是这意味着需要强制转换
我还认为我可以在类中包含结构,并且可以将其作为引用传递,但是提供的任何检索结构成员的方法都将执行复制
另一个想法是公开数据
可以有人告诉我C++中这种情况下的正常解决方案,即C++中返回“const &”的等价性。出于性能原因,我是否希望避免创建结构副本?我可以通过ref将结构作为函数参数传递。我不能返回类成员结构的引用吗
编辑
只是澄清一下,在本例中,我使用的是struct,因为它符合DLL的API,我认为与此API保持一致是很好的。我不是在要求用一个类来代替这个。同样地,我也不想寻找一个使类更复杂的解决方案。
我希望MyCDllApi是c dll的一个简单的非智能c#包装器。我想问的是,是否有任何合理的方法可以避免每次外部对象访问该类以检索DllData时都使用struct copy。也就是说,类似于C++中的“const &”。< /强>
如果这样的解决方案/模式在C#中不常用或不合适,那么这很好。我的程序可以处理结构副本的开销。我只是想问这个问题。
谢谢你的评论,听起来你有三个选择:
类
与[SequentialLayout]
一起使用;参见示例getData()
中返回整个结构,而只返回调用方真正感兴趣的部分。在此基础上的一个变体是传入一个Func
(或Action
)对结构进行操作。这两种技术都避免了复制doSomeWork()
,而不是在C#中实现。这也避免了从C#中的.h文件复制(大)结构
这个结构太小了,你为什么担心它会被复制呢?你可能想重新命名你的问题,以便更能描述这个问题。另外,作为旁注,C#标准是
MethodName()
而不是MethodName()
,匈牙利符号有点不相等。所示的结构就是一个例子。为了简单起见,我把它缩小了。真正的结构是相当大的。它已经这样工作了,结构是可轻击的。因此pinvoke封送器将传递一个指向存储在类对象中的结构的指针,本机代码将直接涂鸦到GC堆中。您正在尝试优化不需要任何帮助的内容。只有在知道性能问题时才优化代码。您可以将类
与顺序布局
一起使用。这已经是一个“指针”,所以将其定义为做一些工作(DllData数据)
。谢谢。我没有更改dll的范围,因此无法执行选项1。我的类的目标是简单地实现c#/c接口,即为c dll提供一个包装器,并让外部类做更多有意义的工作。我不想给类的用户提供限制,也不想在MyCDllApi中执行任何功能,除了作为dll的哑包装器。@user1400716:通过p/invoke封送将涉及复制数据,句号。NET不会让你的C++在你的脚上射击你的C。而且,您可以将数据封送为类
,就像封送结构一样容易;p/Unjk不关心(对于非托管代码也没有C++),<代码>类< /COD>和结构> < />代码完全有相同的实现。嗯,丹的#3建议很可能会让你接近你想要的目标,但问题中没有足够的细节可以确定。@PeterDuniho:可以通过引用来封送blittable类型;在.NET端,它们作为ref
参数传递,而在本机端,它们被声明为指针。当.NET通过引用传递包含在对象字段中的结构时,该对象将被固定,直到该方法返回为止。@supercat:谢谢,你说得对。在这种情况下,.NET确实让你的C++在你的脚上射击你的C。因此,基本上:OP的代码已经完成了他要求它做的事情,只要他坚持使用struct
。