Tag: marshalling

IntPtr算术

我试图以这种方式分配一个结构数组: struct T { int a; int b; } data = Marshal.AllocHGlobal(count*Marshal.SizeOf(typeof(T)); … 我想访问分配的数据“绑定”一个结构到分配给AllocHGlobal的数组中的每个元素…像这样的东西 T v; v = (T)Marshal.PtrToStructure(data+1, typeof(T)); 但我没有找到任何方便的方法… 为什么IntPtr缺乏算术 ? 我该如何以“安全”的方式解决这个问题? 有人可以确认PtrToStructure函数将数据复制到struct变量中吗? 换句话说,修改结构体是否反映了结构数组数据中的修改? 当然,我想对使用struct的IntPtr指向的数据进行操作,而不是每次都复制数据,避免不安全的代码。 谢谢大家!

为什么C#和VB.NET以不同的方式隐式编组char *?

所以我有一个用C ++编写的函数,看起来像这样…… extern “C” __declspec(dllexport) int __stdcall SomeFunction(char *theData) { // stuff } …我在我当前的项目中使用它(用C#编写)。 还有其他项目使用VB编写的这个函数,如下所示: Public Declare Function SomeFunction Lib “MyDLL.dll” _ Alias “_SomeFunction@4” (ByVal theData As String) As Integer 所以我尝试在C#中编写一个等价物,但是发现使用字符串类型对我来说实际上并不起作用 – 字符串会返回我传递给它的相同数据。 我尝试使用”ref string”代替通过引用传递字符串,我得到了内存访问冲突。 在做了一些挖掘之后,我发现这是C#中正确的实现: [DllImport(“MyDLL.dll”, EntryPoint = “_SomeFunction@4”)] public static extern int SomeFunction(StringBuilder theData); 现在我知道VB.NET和C#是完全不同的,但我想我总是认为字符串是字符串。 如果一种语言可以隐式地将char*送到String ,为什么不能另一种语言,需要一个完全不同的类? (为清晰起见编辑了标题)

无法从其他STA线程调用从STAThread创建的COM对象

我是COM的新手,试图了解STA和MTA之间的区别。 我试图创建一个示例,该示例将显示COM可以管理在STA中创建的对象的调用,该对象不是线程安全的。 这里的MyCalcServer类是使用ATL Simple Object创建的。 使用的设置与本文中的相同: 线程模型:公寓 聚合:没有 界面:自定义 MyCalcServer COM对象用于另一个C#项目,它是: class Program { [STAThread] static void Main(string[] args) { MyCOMLib.MyCalcServer instance = new MyCOMLib.MyCalcServer(); string output1; instance.ChangeValue(“Gant”, out output1); Console.WriteLine(output1); Thread t1 = new Thread(() => { while (true) { string output; instance.ChangeValue(“Gant”, out output); Console.WriteLine(output); } }); t1.SetApartmentState(ApartmentState.STA); t1.Start(); // : // also […]

如何在C#中固定指向托管对象的指针?

非托管代码调用我的函数。 在第一个函数中,我应该将指针传递给我的托管对象。 有时候稍后我的其他一些函数会被调用与指针之一相同的指针。 我应该取消引用它并使用它来执行一些计算,然后如果不需要处理它。 为了简化故事,我需要固定该对象,以便GC在我处理它之前不会移动它。 如何在C#中做到这一点? 提前致谢。

如何在C#,2012版中正确清理Excel互操作对象

我正在用C#编写一个应用程序,它将通过互操作打开一个Excel电子表格(2007年,现在),做一些魔术,然后关闭。 “魔术”部分非常重要,因此该应用程序将包含对Excel生成的许多COM对象的许多引用。 我以前写过这种应用程序(事实上已经太多次了)但是我从来没有找到一种舒适的,“好闻”的方法来与COM对象进行交互。 问题部分在于,尽管进行了大量研究,我仍然不能完全理解COM,部分是因为互操作包装器隐藏了很多可能不应该隐藏的内容。 事实上,来自社区的这么多不同的,相互冲突的建议只会让事情变得更糟。 如果您无法从标题中分辨出来,我已经完成了我的研究。 标题暗示了这篇文章: 如何正确清理Excel互操作对象? 在2008年首次询问时,这个建议在当时非常有用且非常可靠(特别是“从不使用带有com对象的2个点”位),但现在看来已经过时了。 2010年3月,Visual Studio团队发布了一篇博客文章,警告其他程序员Marshal.ReleaseComObject [is] Considered Dangerous 。 文章提到了两篇文章, cbrumme的WebLog> ReleaseComObject以及接口指针和运行时可调用包装器(RCW)之间的映射 ,表明人们一直错误地使用ReleaseComInterop(cbrumme:“如果你是一个使用适度数量的客户端应用程序在托管代码中自由传递的COM对象,不应使用ReleaseComObject“)。 有没有人有一个中等复杂的应用程序的例子,最好使用多个线程,能够成功地在内存泄漏之间导航(Excel在应用程序关闭后继续在后台运行)和InvalidComObjectExceptions? 我正在寻找能够在创建它的上下文之外使用COM对象的东西,但是一旦应用程序完成它仍然可以清理它:内存管理策略的混合,可以有效地跨越托管/非管理鸿沟。 对于讨论这个问题的正确方法的文章或教程的引用将是一个非常受欢迎的替代方案。 我最好的Google-fu努力已经返回了显然不正确的ReleaseComInterop方法。 更新: (这不是答案) 发布后不久我发现了这篇文章: Jake Ginnivan的VSTO和COM Interop 我已经能够通过扩展方法实现他在“AutoCleanup”类中包装COM对象的策略,我对结果非常满意。 虽然它没有提供允许COM对象跨越创建它们的上下文边界的解决方案,并且仍然使用ReleaseComObject函数 ,但它至少提供了一个简洁易读的解决方案。 这是我的实现: class AutoCleanup : IDisposable { public T Resource { get; private set; } public AutoCleanup( T resource ) { this.Resource = resource; […]

C#中的struct marshal

我在C#中有以下结构 unsafe public struct control { public int bSetComPort; public int iComPortIndex; public int iBaudRate; public int iManufactoryID; public byte btAddressOfCamera; public int iCameraParam; public byte PresetNum; public byte PresetWaitTime; public byte Group; public byte AutoCruiseStatus; public byte Channel; public fixed byte Data[64]; } 我用来将它转换为字节数组[]的函数是 static byte[] structtobyte(object obj) { int len = Marshal.SizeOf(obj); byte[] […]

在C#中编组char **

我正在接受带有char**代码(即指向字符串的指针): int DoSomething(Whatever* handle, char** error); 基本上,它需要处理其状态,如果出现问题,它会返回错误代码和可选的错误消息(内存分配在外部,并使用第二个函数释放。这部分我已经指出:))。 但是,我不确定如何处理C#。 我目前所拥有的: [DllImport(“mydll.dll”, CallingConvention = CallingConvention.Cdecl)] private static unsafe extern int DoSomething(IntPtr handle, byte** error); public static unsafe int DoSomething(IntPtr handle, out string error) { byte* buff; int ret = DoSomething(handle, &buff); if(buff != 0) { // ??? } else { error = “”; } return ret; } […]

使用C#中的Marshal.StructureToPtr将结构传递给C ++ API

我在我的代码中使用C ++编写的API(用C#编写)。 API需要一个参数作为指向结构的指针。 结构由“Int”和Char Arrays组成:例如 unsafe public struct ToBePassed { Int32 Num1; Int32 Num2; Char[] Data; // or fixed Char Data[255]; } 我不能直接将结构指针传递给API,因为在这种情况下,我收到错误,因为“指针不能引用Marshaled结构”。 代码编译成功但是当我执行(调试)代码时会出现此错误。 现在我有两个选择:第一: – 通过Ref传递结构:我想问一下当我通过ref传递结构时,需要结构指针的API是否可以接收地址。 请注意,API将在“Char [] Data”中返回Data。 第二: – 使用Marshal.StructureToPtr:这会将结构指针转换为IntPtr。 怀疑是相同的,API会正确接收吗? 谢谢你的时间! 此致,Swanand

如何将函数从C ++ DLL正确导入到C#Project中

我可以使用如何正确地将C ++ DLL中的几个函数导入到我的C#应用​​程序中的帮助。 以下是C ++方面的一些示例,它们展示了我在C#中尝试做的事情。 我不认为我正确地编组了一些/或一些返回类型和一些参数(尤其是指针/ ref / out)。 C ++头文件声明: unsigned long __stdcall mfcsez_initialisation(unsigned short serial); unsigned char __stdcall mfcs_get_serial(unsigned long int handle, unsigned short * serial); unsigned char __stdcall mfcs_read_chan(unsigned long int handle, unsigned char canal, float * pressure, unsigned short * chrono); C ++代码: /* Define functions prototype */ typedef unsigned long(__stdcall […]

C#字符串编组和LocalAlloc

我有一个来自非托管DLL的COM回调,我需要在C#中使用它。 非托管DLL期望被调用者使用LocalAlloc (调用者将使用LocalFree )分配内存,使用WSTR填充它并分别设置value和chars到WSTR指针和字符串长度。 代码片段我正在尝试转换为C#: STDMETHODIMP CMyImpl::GetString(LPCSTR field, LPWSTR* value, int* chars) { CStringW ret; if (!strcmp(field, “matrix”)) { ret = L”None”; if (…) ret.Append(L”001″); else if (…) ret.Append(L”002″); else ret.Append(L”003″); } if (!ret.IsEmpty()) { int len = ret.GetLength(); size_t sz = (len + 1) * sizeof(WCHAR); LPWSTR buf = (LPWSTR)LocalAlloc(LPTR, sz); if (!buf) { […]