标签: pinvoke

如何在涉及指针时进行P/Invoke

为了学习在C#中使用PInvoke,我有点不确定如何使用涉及简单值类型的指针处理各种情况.

我从非托管DLL导入以下两个函数:

public int USB4_Initialize(short* device);
public int USB4_GetCount(short device, short encoder, unsigned long* value);
Run Code Online (Sandbox Code Playgroud)

第一个函数使用指针作为输入,第二个函数使用指针作为输出.它们在C++中的用法相当简单:

// Pointer as an input
short device = 0; // Always using device 0.
USB4_Initialize(&device);

// Pointer as an output
unsigned long count;
USB4_GetCount(0,0,&count); // count is output
Run Code Online (Sandbox Code Playgroud)

我在C#中的第一次尝试导致以下P/Invokes:

[DllImport("USB4.dll")]
public static extern int USB4_Initialize(IntPtr deviceCount); //short*

[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, IntPtr value); //ulong*
Run Code Online (Sandbox Code Playgroud)

如何在C#中使用这些函数的方式与上面的C++代码相同?有没有更好的方法来声明这些类型,也许使用MarshalAs

c# pinvoke dllimport

8
推荐指数
1
解决办法
7530
查看次数

在 p 调用非托管 DLL 时获取标准输出?

我有一个非托管的 DLL,它正在将日志消息写入标准输出。我正在使用来自 WPF 应用程序的 P 调用调用此 DLL,我需要获取标准输出流日志。我试过 Console.SetOut,但这似乎只能捕获使用 Console.Write 等编写的信息。

谁有想法?我在其他地方发现了类似的问题,但他们没有答案。

c# pinvoke stdout

8
推荐指数
1
解决办法
3886
查看次数

"使用"vs [DllImport]?

我想知道什么是最顶级声明的引用,为什么我们仍然需要使用DllImport?我在说C#.

c# pinvoke using dllimport

8
推荐指数
2
解决办法
6437
查看次数

将C结构编组为C#

假设我有一个结构:

typedef struct {
float x;
float y;
float z;
int   ID;
} Vertex;
Run Code Online (Sandbox Code Playgroud)

和一个C++函数:

float first(Vertex* ptr, int length){ //really silly function, just an example
    Vertex u,v;
    u.x = ptr[0].x; //...and so on, copy x,y,z,ID
    v.x = ptr[1].x; 
    return (u.x * v.x + u.y * v.y + u.z * v.z);
    }


Vertex* another(float a, int desired_size){
    Vertex v = (Vertex*)malloc(desired_size*sizeof(Vertex));
    v[0].x = a;
    v[1].x = -a; //..and so on.. make some Vertices.
    return v;
}
Run Code Online (Sandbox Code Playgroud)

首先 - 我的IDE.我正在使用Visual Studio …

.net c# dll pinvoke interop

8
推荐指数
1
解决办法
4483
查看次数

DllImport,如何检查DLL是否已加载?

我正在进行P/Invoke,我使用以下方法

[DllImport("Authz.dll", SetLastError = true)]
    public static extern BOOL AuthzFreeContext(
        IntPtr phAuthzResourceManager);
Run Code Online (Sandbox Code Playgroud)

即使它工作,如何保证Authz.dll始终加载到我的代码中.假设我dll是一些XXX.dll如何在使用之前检查是否加载了dll,这样我就不会找到找不到方法的方法.

c# pinvoke

8
推荐指数
1
解决办法
4183
查看次数

为C#包装本机DLL

我写了一个C++ DLL,现在我需要从托管应用程序调用本机函数.

导出的本机函数如下所示:

extern "C" __declspec(dllexport) 
bool NativeMethod(char *param1, char *param2, char *result);
Run Code Online (Sandbox Code Playgroud)

所以,从C#我将调用该函数传递2个输入参数,1个输出参数,显然我将读取返回bool值.

我试图以多种方式包装所有这些,但总是我得到一个PInvokeStackImbalance例外.我知道调用本机函数的唯一方法是通过应用CallingConvention = CallingConvention.Cdecl).NET函数声明.但是通过这种方式,我无法读取输出参数(它总是空字符串),并且返回值始终为true.

c# c++ string pinvoke

8
推荐指数
1
解决办法
2万
查看次数

keybd_event需要KEYEVENTF_EXTENDEDKEY说明

文档中它说:

KEYEVENTF_EXTENDEDKEY(0x0001):如果指定,则扫描代码前面有一个值为0xE0(224)的前缀字节.

有人可以解释这意味着什么吗?

这有什么区别:

keybd_event(RIGHT, 0, 0, 0);
keybd_event(RIGHT, 0, 2, 0);
Run Code Online (Sandbox Code Playgroud)

还有这个:

keybd_event(RIGHT, 0, 1 | 0, 0);
keybd_event(RIGHT, 0, 1 | 2, 0);
Run Code Online (Sandbox Code Playgroud)

因为当我执行这段代码时,我看不出有什么区别?

另外,什么是"字节bScan"?在描述中它是:密钥的硬件扫描代码.那意味着什么?

c# pinvoke keyboard-events

8
推荐指数
3
解决办法
5640
查看次数

在多线程环境中从C#调用Delphi DLL时发生访问冲突

我正在使用P/Invoke从C#调用用Delphi XE2编写的DLL函数.当从单个线程顺序进行调用时,它似乎正在工作.但是,当多个线程调用该函数时,C#主机应用程序System.AccessViolationException似乎随机抛出.

为什么下面的代码会触发访问冲突,我该如何解决?

用于重现问题的最小Delphi库代码:

library pinvokeproblem;

{$R *.res}

uses Windows, SysUtils;

procedure Test(const testByte: byte); stdcall;
begin
  OutputDebugString(PWideChar(IntToStr(testByte)));
end;

exports Test;

end.
Run Code Online (Sandbox Code Playgroud)

用于重现问题的最小C#主机应用程序代码:

[DllImport(
    "pinvokeproblem.dll",
    CallingConvention = CallingConvention.StdCall,
    EntryPoint = "Test")]
private static extern void Test(byte testByte);

public static void Main(string[] args)
{
    for (int i = 1; i <= 1000; i++) // more iterations = better chance to fail
    {
        int threadCount = 10;
        Parallel.For(1, threadCount, new ParallelOptions { MaxDegreeOfParallelism = threadCount }, test =>
        {
            byte …
Run Code Online (Sandbox Code Playgroud)

.net c# delphi pinvoke multithreading

8
推荐指数
1
解决办法
862
查看次数

C#编组布尔

脚本

这应该是一项简单的任务,但由于某种原因,我无法按预期进行.我必须struct在反向P/Invoke调用(非托管调用托管代码)期间编组基本C++ .

只有bool在struct中使用时才出现这个问题,所以我只是将C++方面修改为:

struct Foo {
    bool b;
};
Run Code Online (Sandbox Code Playgroud)

由于.NET默认情况下将布尔值编组为4字节字段,因此我将本机布尔值显式编组为1字节长度字段:

public struct Foo {
    [MarshalAs(UnmanagedType.I1)] public bool b;
}
Run Code Online (Sandbox Code Playgroud)

当我使用以下签名和正文调用导出的托管静态方法时:

public static void Bar(Foo foo) {
    Console.WriteLine("{0}", foo.b);
}
Run Code Online (Sandbox Code Playgroud)

我打印出正确的布尔alpha表示.如果我使用更多字段扩展结构,则对齐是正确的,并且在编组后数据不会损坏.

问题

出于某种原因,如果我不将此编组struct作为参数传递,而是通过值传递返回类型:

public static Foo Bar() {
    var foo = new Foo { b = true };
    return foo;
}
Run Code Online (Sandbox Code Playgroud)

应用程序崩溃时出现以下错误消息:

在此输入图像描述

如果我更改托管结构以保持byte而不是abool

public struct Foo {
    [MarshalAs(UnmanagedType.I1)] public byte b;
}

public static Foo Bar() {
    var foo = new …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke interop marshalling

8
推荐指数
1
解决办法
5555
查看次数

列出当前活动的CreateWaitableTimer事件

尝试查找仍处于待处理状态的任何当前活动计时器,这可能会导致计算机唤醒.创建计时器时,会指定名称.所有指定计时器的列表都是理想的,而不仅仅是指定的名称.

以下是创建命名计时器的代码:

[DllImport("kernel32.dll")]
private static extern SafeWaitHandle CreateWaitableTimer(IntPtr lpTimerAttributes, bool bManualReset, String lpTimerName);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool SetWaitableTimer(SafeWaitHandle hTimer, [In] ref long pDueTime, int lPeriod, IntPtr pfnCompletionRoutine, IntPtr lpArgToCompletionRoutine, bool fResume);

private static int SetWaitForWakeUpTime(DateTime wakeTime) {
    long waketime = wakeTime.ToFileTime();

    String timerName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name.ToString() + "WakeUpTimer";
    using (SafeWaitHandle handle = CreateWaitableTimer(IntPtr.Zero, true, timerName)) {
        if (SetWaitableTimer(handle, ref waketime, 0, IntPtr.Zero, IntPtr.Zero, true)) {
            using (EventWaitHandle wh = new EventWaitHandle(false, EventResetMode.AutoReset)) {
                wh.SafeWaitHandle = …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke dllimport

8
推荐指数
1
解决办法
151
查看次数