我使用一些旧的API,需要将结构的指针传递给异步运行的非托管代码.
换句话说,在我将struct指针传递给非托管代码之后,非托管代码会复制指针并立即返回.非托管代码可以在后台访问该结构,在另一个线程中.我无法控制在另一个线程和线程本身中运行的非托管代码.
fixed {}语句不能用于固定,因为它不是为异步非托管固定而设计的.
GCHandle只能引用引用,因此必须将结构框设置为使用GCHandle.我尝试过,它的确有效.它的主要问题是您无法从托管代码更新结构.要更新结构,首先我们需要将其取消装箱,然后更新,然后再次装箱,但是......哎呀......再次装箱?!?这意味着内存中的前一个指针仍然指向旧的非最新结构,而新结构有另一个指针,这意味着我需要将新指针传递给非托管代码...不适用于我的案件.
如何在没有固定{}语句的情况下在内存中固定结构,以便我可以在不更改指针的情况下从托管代码更新它?
谢谢.
编辑:
只是想...有没有办法固定包含结构的父对象,然后获取结构的指针而不是容器对象?
有人可以向我解释一下un/managed DLL是什么?什么是un /托管代码?
在询问手动管理CLR内存的过程中,我意识到我知之甚少.
我知道当你退出托管上下文时,CLR会在堆栈上放置一个'cookie',这样垃圾收集器就不会破坏你的内存空间; 但是,在我读过的所有内容中,我都假设您正在调用一些用C语言编写的库.
我希望在托管上下文之外的C#中使用我的应用程序的整个写层来管理低级别的数据.然后,我想从托管图层访问此图层.
在这种情况下,我的Unmanaged C#代码是否会编译为IL并在CLR上运行?这是如何运作的?
我的问题始于将.Net 2.0应用程序移动到.Net 4.0.我必须这样做的原因是Windows 8默认情况下不启用早期的.Net版本,我的应用程序无法要求用户启用它.
该应用程序是一个NPAPI插件,它通过UnmanagedExports使用.Net组件.我将其设计为低完整性应用程序,因此它必须驻留在用户的LocalLow'目录中.
在我的应用程序中,我使用动态程序集加载机制在运行时加载多个程序集.我使用以下方法加载程序集,
MyInterface Instance;
Assembly assembly = Assembly.LoadFrom(AssemblyFile);
Type type = assembly.GetType(Identifier); // Identifier is implementing the MyInterface
Instance = Activator.CreateInstance(type) as MyInterface;
// Do something with the Instance
Run Code Online (Sandbox Code Playgroud)
将项目修改为.Net 4.0之后,我注意到当二进制文件放在LocalLow目录中时插件崩溃(它在其他地方工作).我的下一步是创建一个简约插件,用尽可能少的代码来找出问题.我注意到动态程序集加载失败,出现以下异常,
System.IO.FileLoadException: Could not load file or assembly '<assemblyPath>' or one of its dependencies. Operation is not supported. (Exception from HRESULT: 0x80131515 (COR_E_NOTSUPPORTED)) --->
System.NotSupportedException: An attempt was made to load an assembly from a network location which would have caused the …Run Code Online (Sandbox Code Playgroud) 我有一个ac#应用程序,它依赖于第三方非托管程序集来访问某些硬件.
非托管代码存在内存泄漏,每次访问后内存消耗会增加~10mb.问题是众所周知的; 没有bugfix可用.
有没有办法可以继续使用这个程序集而无需定期重启?
我尝试创建一个单独的AppDomain,将有问题的代码加载到该AppDomain中appDomain.CreateInstanceAndUnwrap(),然后通过以下方式卸载域AppDomain.Unload().但是,这显然不会释放该域使用的非托管内存,只释放托管内存.
我还可以将应用程序拆分为两个独立的部分,并仅重新启动具有非托管dll的部分.然而,这将意味着重大的重新设计,并且可能导致大量的减速,因为必须在这两个部分之间交换大量数据.
是否有另一种方法可以驯服这个漏出的程序集并强制它释放内存而不重新启动.
我试图定义一个属性,返回指向泛型类型参数的指针,如下所示:
public class MemWrapper<T> where T: struct
{
readonly IntPtr pointerToUnmanagedHeapMem;
// ... do some memory management also ...
public unsafe T* Ptr
{
get {return (T*)(pointerToUnmanagedHeapMem);}
}
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨无法声明指向托管类型T的指针或获取其地址或大小(CS0208).奇怪的是,如果我用一个具体的结构手动替换泛型类型参数,那就是
public class MyStructMemWrapper
{
readonly IntPtr pointerToUnmanagedHeapMem;
// ... do some memory management also ...
public unsafe MyStruct* Ptr
{
get {return (MyStruct*)(pointerToUnmanagedHeapMem);}
}
}
Run Code Online (Sandbox Code Playgroud)
一切都很好.但是,我必须为我使用的每个结构创建一个特殊版本的包装器.那么为什么通用甚至关心它正在铸造什么样的不安全指针呢?
背景信息:我使用的是本机dll,它反过来调用我的c#回调函数,并将其作为指针传递给我最常用的用户数据结构(更准确地说:伪装成IntPtr).为了能够传递GC稳定指针,我在非托管堆上分配我的用户数据结构.因此,我必须注意最后再次释放内存.
由于这是当然都在一个什么样的忠实C#程序员可以承受的极限,我创建一个包装类(周围堆分配和指针的使用情况,以结构)分开我尽可能多地从丑陋的东西.为了尽可能方便地为非托管堆上的结构赋值,我想定义上面的属性.
public struct MyStruct {public double x;}
// ...
MemWrapper<MyStruct> m = new MemWrapper<MyStruct>();
unsafe
{
// ideally I would like to …Run Code Online (Sandbox Code Playgroud) 我正在尝试从一个字节数组创建一个双重托管数组.我目前有问题,但我想优化.这是我想要使用的一些代码:
private unsafe static double[] _Get_Doubles(byte[] _raw_data)
{
double[] ret;
fixed (byte* _pd = _raw_data)
{
double* _pret = (double*)_pd;
ret = (double[])*_pret; //FAILURE
}
}
Run Code Online (Sandbox Code Playgroud)
请让我知道如何处理这些问题.
-Aaron
我正在编写一个非常高性能的应用程序,每毫秒处理和处理数百个事件.
Unmanaged C++比托管c ++更快吗?为什么?
托管C++处理CLR而不是OS和CLR负责内存管理,这简化了代码,并且可能比非托管C++中"程序员"编写的代码更有效?还是有其他原因?当使用托管时,如果对程序员透明并由CLR处理,那么如何避免动态内存分配(这会导致性能损失)?
回到我的问题,托管C++在速度方面是否比非托管C++更有效?为什么?
注意:最终的工作解决方案是在编辑之后!
我希望有人可以帮我解决过去几天我一直试图解决的问题.
我试图将结构从非托管C++ DLL传递给C#脚本.这是我到目前为止:
C++
EXPORT_API uchar *detectMarkers(...) {
struct markerStruct {
int id;
} MarkerInfo;
uchar *bytePtr = (uchar*) &MarkerInfo;
...
MarkerInfo.id = 3;
return bytePtr;
}
Run Code Online (Sandbox Code Playgroud)
C#
[DllImport ("UnmanagedDll")]
public static extern byte[] detectMarkers(...);
...
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 1)]
public struct markerStruct
{
[MarshalAs(UnmanagedType.U4)]
[FieldOffset(0)]
public int Id;
}
...
markerStruct ByteArrayToNewStuff(byte[] bytes){
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned);
markerStruct stuff = (markerStruct)Marshal.PtrToStructure(
handle.AddrOfPinnedObject(), typeof(markerStruct));
handle.Free();
return stuff;
}
...
print(ByteArrayToNewStuff (detectMarkers(d, W, H, d.Length) …Run Code Online (Sandbox Code Playgroud) 我有一个非托管库,它有这样的功能:
type* foo();
Run Code Online (Sandbox Code Playgroud)
foo基本上通过分配托管type堆上的非托管实例Marshal.AllocHGlobal.
我有一个托管版本type.它不是blittable但我MarshalAs在成员上设置属性,所以我可以使用它Marshal.PtrToStructure来获得它的托管版本.但不得不foo用额外的簿记打电话来打电话Marshal.PtrToStructure有点烦人.
我希望能够在C#方面做这样的事情:
[DllImport("mylib", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.LPStruct)]
type* foo();
Run Code Online (Sandbox Code Playgroud)
让C#的marshaller处理幕后转换,就像它对函数参数一样.我以为我应该能够这样做因为type在托管堆上分配了.但也许我不能?有没有办法让C#的内置编组器为我处理返回类型的非托管到托管转换而无需手动调用Marshal.PtrToStructure?