我正在查看ChangeDisplaySettings的 MSDN 文档。对于 dwFlags 选项,您可以传入 0 或其他列出的标志之一。但是,我无法弄清楚如何直接引用这些标志,也无法弄清楚它们的实际long值是什么来代替它们。
我使用以下命令从 C# 应用程序进行这些调用:
[DllImport("User32.dll")]
public static extern long ChangeDisplaySettings(ref DeviceMode lpDevMode, int dwflags);
Run Code Online (Sandbox Code Playgroud)
有没有办法可以直接引用这些标志,或者,除此之外,找出它们的实际值是什么?
我已经阅读了一些文档,这是我用于 IntPtr 操作的类,以使它们更安全:
internal class MySafeHandleOperator : SafeHandleZeroOrMinusOneIsInvalid
{
public MySafeHandleOperator(IntPtr handle) : base(true)
{
SetHandle(handle);
}
public IntPtr GetPtr()
{
return this.handle;
}
protected override bool ReleaseHandle()
{
this.Dispose(true);
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
主要问题在ReleaseHandle方法中。我已经以这种方式使用过它,但我很好奇这是否是正确的使用方式?可能还有另一种正确的方法来释放句柄并清除此类?
我想以类似的方式使用此类(一个简单的示例):
Process p = Process.Start(processName);
MySafeHandleOperator mh = new MySafeHandleOperator(p.MainWindowHandle);
Run Code Online (Sandbox Code Playgroud)
如果有人能看一下并说我是否做对了一切,或者这个方法需要重写,我将不胜感激。
我有一些本机 dll,必须根据平台条件将其复制到 bin 文件夹中。我希望将它们复制到引用该项目的项目的 bin 文件夹中。
如果我将构建操作设置为Content,它们将被复制到 bin 文件夹,但保留文件夹结构,因此它们不会位于 bin 文件夹中,而是位于子文件夹中。因此,当运行程序时,它将无法解析 dll,因为它们位于子文件夹中。
例如,如果我的项目文件中有此代码
<Choose>
<When Condition=" '$(Platform)'=='x86' ">
<ItemGroup>
<Content Include="nativedll\somelib\x86\somelib.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</When>
<When Condition=" '$(Platform)'=='x64' ">
<ItemGroup>
<Content Include="nativedll\somelib\x64\somelib.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</When>
</Choose>
Run Code Online (Sandbox Code Playgroud)
bin\nativedll\somelib\x86\somelib.dll如果是 x86,该 dll 将位于该文件夹中。
所以我尝试使用构建后脚本
<PostBuildEvent>
IF "$(Platform)" == "x86" (
xcopy /s /y "$(ProjectDir)\nativedll\somelib\x86" "$(TargetDir)"
)
IF "$(Platform)" == "x64" (
xcopy /s /y "$(ProjectDir)\nativedll\somelib\x64" "$(TargetDir)"
)
</PostBuildEvent>
Run Code Online (Sandbox Code Playgroud)
但是 dll 被复制到项目的 bin 文件夹中,而不是复制到引用它的项目的 bin 文件夹中。
所以我现在的解决方案是在使用此脚本的所有项目中添加一个构建后脚本。
在 Visual Studio …
在 C 中,您可以编译一个静态库,该库依赖于定义多个函数的 C 头文件。您不需要知道哪个库最终将实现这些函数,因此您的静态库可以与实现无关。只要您提供有效的实现,您就可以将静态库链接到最终的可执行文件中。
我怎样才能在 C# 中做类似的事情?我想创建一个依赖于可由多个 C++ DLL 实现的通用 API 的库。(需要明确的是,我的意思是动态链接,而不是像上面的类比那样的静态链接。)但是要使用DllImportP/Invoke,我必须提供 DLL 名称。显然,我必须在某个时候这样做,但我想创建一个类库 DLL,它依赖于当时未指定的 DLL 中的 API,然后仅在最终版本中提供该非托管 DLL 的名称应用项目。
我有一个非托管的C++库.我想公开.NET应用程序的功能.有一个部分功能我不知道如何处理:
typedef void(free_fn*)(void*); void put(void*data,free_fn deallocation_function);
我们的想法是将动态分配的缓冲区传递给函数并提供释放函数.该库将异步处理数据,并在以后不再需要数据时释放缓冲区:
void*p = malloc(100); ...填写缓冲区... put(p,free);
我如何向.NET应用程序公开这种东西?
我有这段代码(来自诺基亚PC连接3.2示例代码,在C#中):
DAContentAccessDefinitions.CA_FOLDER_INFO folderInfo =
new DAContentAccessDefinitions.CA_FOLDER_INFO();
folderInfo.iSize = Marshal.SizeOf(folderInfo); //(32)
IntPtr bufItem = Marshal.AllocHGlobal(folderInfo.iSize);
//I often get a AccessViolationException on the following line
Marshal.StructureToPtr(folderInfo, bufItem, true);
Run Code Online (Sandbox Code Playgroud)
如果我GC.Collect()在开始时运行,那么我没有得到AccessViolationException.但除非必要,否则我不想放慢这个功能.我尝试GC.Keepalive过各种各样的地方,但没有成功.
CA_FOLDER_INFO 定义为:
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Unicode)]
public struct CA_FOLDER_INFO
{
public int iSize;
public int iFolderId;
public int iOptions;
public string pstrName;
public string pstrPath;
public int iSubFolderCount;
public IntPtr pSubFolders;
public IntPtr pParent;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我不需要任何一个字符串,并且更改它们的定义IntPtr似乎会使异常消失.
这里发生了什么,以及防止异常的正确方法是什么?
从C#应用程序调用本机库中的函数有什么缺点?对性能影响我能期待什么?这些函数是基本的工程计算,并没有太复杂.我们可以在某天用C#重写它们.
我有这个方法,我需要在我的应用程序中调用和使用,但我不知道真的知道如何完成它.
这是我需要调用的功能.
[DllImport(dll_Path)]
public static extern int DTS_GetDataToBuffer(int Position, int Length, char* Buffer, int* DataRead);
Run Code Online (Sandbox Code Playgroud)
在我的代码中,我有这个功能,我错过了它的实现.
internal static void GetDataToBuffer(int position, int length, out byte[] data, out int dataRead)
{
unsafe
{
// the code I need
}
}
Run Code Online (Sandbox Code Playgroud)
我认为大部分都是非常自我规划的.我需要实现后一个函数,这样我才能将数据读入缓冲区和读取的数据量(实际上应与data.Length相同,但制造商将此作为单独的选项,所以我需要它).有人可以帮忙吗?这够清楚了吗?
谢谢
编辑:这是.h文件中的非托管声明.希望能帮助到你.
extern NAG_DLL_EXPIMP int DTS_GetDataToBuffer(int Position,
int Length,
unsigned char *Buffer,
int *DataRead );
Run Code Online (Sandbox Code Playgroud)
编辑#2:位置 - 星形读取数据的位置.长度 - 要读取的数据量(这将是缓冲区大小).DataRead - 读取的实际数据大小.
是否可以为MarshalAs属性类定义自定义UnmanagedType?具体来说,我想将long int unix时间转换为DateTime类型.像这样的东西:
[MarshalAs(UnmanagedType.LongTimeUnix)]
public DateTime Time;
Run Code Online (Sandbox Code Playgroud)
我在哪里放置自定义LongTimeUnix枚举类型以及放置时间转换代码的位置:
public static DateTime ConvertUnix2DateTime(long timeStamp)
{
DateTime DT = new DateTime(1970, 1, 1, 0, 0, 0, 0);
DT = DT.AddSeconds(timeStamp);
return DT;
}
Run Code Online (Sandbox Code Playgroud)
使用时传输数据
(SomeStruct)Marshal.PtrToStructure(
IntPtr,
typeof(SomeStruct));
Run Code Online (Sandbox Code Playgroud)
我希望长时间使用上面的代码sinppet自动转换unix.我是否必须继承MarshalAs类并将转换写入此类?谢谢,Juergen
更新 这里是自定义编组:
class MarshalTest : ICustomMarshaler
{
public void CleanUpManagedData(object ManagedObj)
{
throw new NotImplementedException();
}
public void CleanUpNativeData(IntPtr pNativeData)
{
throw new NotImplementedException();
}
public int GetNativeDataSize()
{
return 8;
}
public IntPtr MarshalManagedToNative(object ManagedObj)
{
throw new NotImplementedException();
}
public object MarshalNativeToManaged(IntPtr …Run Code Online (Sandbox Code Playgroud) 我有一个用VC++ MFC 6.0编写的应用程序.最近通过在vs2008中编译升级到.NET 3.5,并通过使用托管和非托管环境向其添加了一些WPF应用程序.基本上在win32窗口上托管WPF.如果我只是打开一个WPF应用程序窗口,内存会持续上升到1KB/10秒.我尝试过使用.NET Memory Profiler和Ants内存分析器.但两者都无法帮我检测泄漏!我已从托管的WPF应用程序中删除了所有WPF控件.它只包含一个只有一个框架的页面.但仍然发生泄漏!! 有人请帮助我什么可能导致应用程序内存上升?
unmanaged ×10
c# ×8
.net ×3
dllimport ×2
managed ×2
allocation ×1
c++ ×1
dll ×1
handle ×1
header-files ×1
intptr ×1
marshalling ×1
memory ×1
memory-leaks ×1
nokia ×1
unsafe ×1
wpf ×1