我想编组一个与P/Invoke一起使用的结构,但是这个结构包含一个只与我的托管代码相关的字段,因此我不希望它被编组,因为它不属于本机结构.它甚至可能吗?我正在寻找类似于NonSerialized序列化的属性,但它似乎不存在......
struct MyStructure
{
int foo;
int bar;
[NotMarshaled] // This attribute doesn't exist, but that's the kind of thing I'm looking for...
int ignored;
}
Run Code Online (Sandbox Code Playgroud)
任何建议将不胜感激
我正在努力为软件SDK的DLL文件,我试图调用一个函数来获取有关软件主机的信息.
在函数想要的结构中有两个unsigned char变量(HostMachineAddress,HostProgramVersion),当我尝试从c#调用它时,我似乎"松散"了最后一个字节...如果我将下面的c#struct中的SizeConst更改为5我确实得到了丢失的字节,但是它导致另一个变量丢失了数据.
有人可以帮我找到解决这个问题的方法吗?也尝试使用类而不是struct导致system.stackoverflow错误
C#Struct
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct sHostInfo
{
public int bFoundHost;
public int LatestConfirmationTime;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szHostMachineName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string HostMachineAddress;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
public string szHostProgramName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 4)]
public string HostProgramVersion;
}
Run Code Online (Sandbox Code Playgroud)
C#
[DllImport("Cortex_SDK.dll")]
public static extern int GetHostInfo(out sHostInfo pHostInfo);
Run Code Online (Sandbox Code Playgroud) 我有一个库函数返回GetLastError代码(像这样的东西).我需要将它们与特定的错误进行比较,比如ERROR_INVALID_HANDLE.但是我自己定义常量并不舒服.所以问题是,为此目的是否有预定义的枚举?
我们正在使用VS 2010测试运行器(MSTest)进行自动功能测试.当我们从Visual Studio运行测试时,VS会创建一个名为QTAgent32.exe的进程,并在该进程中运行测试.
我们发现当我们进行多次测试运行时,MSTest将重用相同的QTAgent32进程 - 进程ID不会改变.这对我们来说是一个问题,因为我们正在测试的代码是P /调用非托管DLL.DLL需要在进程的生命周期内初始化一次.我们有一个[AssemblyInitialize]方法,但每次测试运行一次.如果我们执行多次测试运行,它将在同一进程中执行多次.
每次我们进行测试运行时,MSTest都会创建一个新的appdomain; 但这些appdomains都在同一个过程中.
所以我想知道:有没有办法告诉Visual Studio测试运行器每次运行测试时都使用新进程?我查看了".testsettings"配置,但没有看到任何相关内容.
我正在玩codeproject的一个项目,它基本上监视计算机上的打印活动.但是,对于64位配置,它无法正常工作.代码的下面部分是问题.打印完成后,将调用此代码.
PRINTER_NOTIFY_INFO info = (PRINTER_NOTIFY_INFO)Marshal.PtrToStructure(pNotifyInfo, typeof(PRINTER_NOTIFY_INFO));
int pData = (int)pNotifyInfo + Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO));
PRINTER_NOTIFY_INFO_DATA[] data = new PRINTER_NOTIFY_INFO_DATA[info.Count];
for (uint i = 0; i < info.Count; i++)
{
data[i] = (PRINTER_NOTIFY_INFO_DATA)Marshal.PtrToStructure((IntPtr)pData, typeof(PRINTER_NOTIFY_INFO_DATA));
pData += Marshal.SizeOf(typeof(PRINTER_NOTIFY_INFO_DATA));
}
Run Code Online (Sandbox Code Playgroud)
调试显示数据[i] .field值始终为0.但在32位中它可以正常工作.我认为没有正确定义PRINTER_NOTIFY_INFO_DATA.目前我正在使用以下代码.任何人都可以解决这个问题,以便在64位中正常工作吗?
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_NOTIFY_INFO
{
public uint Version;
public uint Flags;
public uint Count;
}
[StructLayout(LayoutKind.Sequential)]
public struct PRINTER_NOTIFY_INFO_DATA_DATA
{
public uint cbBuf;
public IntPtr pBuf;
}
[StructLayout(LayoutKind.Explicit)]
public struct PRINTER_NOTIFY_INFO_DATA_UNION
{
[FieldOffset(0)]
private uint adwData0;
[FieldOffset(4)]
private uint adwData1;
[FieldOffset(0)]
public PRINTER_NOTIFY_INFO_DATA_DATA …Run Code Online (Sandbox Code Playgroud) 假设存在一个带有纯C接口的本机函数,如下所示,从本机DLL导出:
// NativeDll.cpp
extern "C" void __stdcall FillArray(
int fillValue,
int count,
int* data)
{
// Assume parameters are OK...
// Fill the array
for (int i = 0; i < count; i++)
{
data[i] = fillValue;
}
}
Run Code Online (Sandbox Code Playgroud)
以下P/Invoke工作正常(使用VS2010 SP1测试):
[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
int fillValue,
int count,
[In, Out] int[] data
);
Run Code Online (Sandbox Code Playgroud)
以及这个P /调用,与上面相同,但没有将[In, Out]属性:
[DllImport("NativeDll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern void FillArray(
int fillValue,
int count,
int[] data
);
Run Code Online (Sandbox Code Playgroud)
那么,这些 …
我想知道它是如何DllImport工作的.我需要一个简单的英语解释 - 意思是简单的解释.
它是否与DLL中的导出方法静态链接,如"包含文件"指令/静态库?
或者当它到达C#程序中的执行点时,它是否从DLL动态调用该方法?
在进行P/Invoke时,重要的是使数据布局匹配.
我们可以使用一些属性来控制struct的布局.
例如:
struct MyStruct
{
public bool f;
}
Run Code Online (Sandbox Code Playgroud)
给出大小为4.虽然我们可以告诉编译器使它成为1字节bool以匹配C++类型bool:
struct MyStruct
{
[MarshalAs(UnmanagedType.I1)]
public bool f;
}
Run Code Online (Sandbox Code Playgroud)
给出1的大小.
这些都有道理.但是当我测试固定的bool阵列时,我很困惑.
unsafe struct MyStruct
{
public fixed bool fs[1];
}
Run Code Online (Sandbox Code Playgroud)
给出4个字节的大小.和
unsafe struct MyStruct
{
public fixed bool fs[4];
}
Run Code Online (Sandbox Code Playgroud)
仍然给出4个字节的大小.但
unsafe struct MyStruct
{
public fixed bool fs[5];
}
Run Code Online (Sandbox Code Playgroud)
给出8的大小.
它看起来像在固定的bool数组中,bool元素的大小仍然是1个字节,但是对齐是4个字节.这与C++ bool数组不匹配,后者是1字节大小和对齐方式.
有人能解释一下吗?
更新:我终于找到了,原因是,bool类型在一个结构中,那么该结构永远不会是blittable!因此,不要指望内部具有bool类型的结构与C中的布局相同.
问候,翔.
当我发现令人惊讶的事情(对我而言)时,我测试了生成时间戳的不同方法.
GetSystemTimeAsFileTime使用P/Invoke 调用Windows 比调用DateTime.UtcNow内部使用CLR的包装器的速度快3倍GetSystemTimeAsFileTime.
怎么可能?
public static DateTime UtcNow {
get {
long ticks = 0;
ticks = GetSystemTimeAsFileTime();
return new DateTime( ((UInt64)(ticks + FileTimeOffset)) | KindUtc);
}
}
[MethodImplAttribute(MethodImplOptions.InternalCall)] // Implemented by the CLR
internal static extern long GetSystemTimeAsFileTime();
Run Code Online (Sandbox Code Playgroud)
核心CLR的包装GetSystemTimeAsFileTime:
FCIMPL0(INT64, SystemNative::__GetSystemTimeAsFileTime)
{
FCALL_CONTRACT;
INT64 timestamp;
::GetSystemTimeAsFileTime((FILETIME*)×tamp);
#if BIGENDIAN
timestamp = (INT64)(((UINT64)timestamp >> 32) | ((UINT64)timestamp << 32));
#endif
return timestamp;
}
FCIMPLEND;
Run Code Online (Sandbox Code Playgroud)
我的测试代码使用BenchmarkDotNet:
public …Run Code Online (Sandbox Code Playgroud) 有没有办法(dllimport)在Linux上的.NET Core中实现P/Invoke ?
示例:
我用.net框架编译了C++ MyLib.dll.
如果可以这样使用,或者不支持使用.net-core使用linux调用native win api?
[DllImport("MyLib.dll", CallingConvention = CallingConvention.StdCall)]
internal static extern long NativeMethod();
Run Code Online (Sandbox Code Playgroud)