标签: pinvoke

如何从C#调用C++/CLI?

我有一个用C++实现的类,它负责程序的算术运算,以及一个使用WPF的接口.我使用C#处理输入,但是我如何使用我的C++类?

我已经看到一些关于使托管C++包装类与它交互的注释,但我不知道从哪里开始.我也不知道如何将其与所有其他代码一起编译.我真的找不到这方面的教程,谷歌在托管C++上展示的东西似乎并没有什么帮助.

有什么东西可以帮助我吗?这对我来说似乎并不合理.

编辑尝试m3rLinEz解决方案,但它给我一个BadImageFormatException,我认为这是因为没有生成DLL.我按照所说的做了一切,不知道发生了什么.有任何想法吗?

c# c++ pinvoke managed-c++ c++-cli

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

分析动态pinvoke

我正在使用MSIL分析器,遇到接口问题ManagedToUnmanagedTransitionUnmanagedToManagedTransition回调ICorProfilerCallback.

我想要检索的是有关被调用方法的信息(它所在的名称和模块名称).

到目前为止它工作正常.直到所谓的动态pinvoke发生(详见:http://blogs.msdn.com/b/jonathanswift/archive/2006/10/03/dynamically-calling-an-unmanaged-dll-from-.net-_2800_c_23002900_ .aspx)

在这种情况下IMetaDataImport::GetPinvokeMap失败.还IMetaDataAssemblyImport::GetAssemblyProps返回"dynamic_pinvoke"作为程序集的名称.

profiler_1_0->GetTokenAndMetaDataFromFunction(function_id, IID_IMetaDataImport, (IUnknown**) &imd_import, &md_token);
imd_import->GetPinvokeMap(md_token, &mapping, module_name, buffer_size, &chars_read, &md_module_ref);
// here the fail occurs

profiler_1_0->GetTokenAndMetaDataFromFunction(function_id, IID_IMetaDataAssemblyImport, (IUnknown**) &imd_assembly_import, &md_token);
imd_assembly_import->GetAssemblyFromScope(&md_assembly);
imd_assembly_import->GetAssemblyProps(md_assembly, 0, 0, 0, assembly_name, buffer_size, &chars_read, 0, 0);
// assembly_name is set to "dynamic_pinvoke"
Run Code Online (Sandbox Code Playgroud)

如何通过动态pinvoke获取模块名称(.dll)和函数名称?

c++ pinvoke cil clr-profiling-api

62
推荐指数
1
解决办法
1855
查看次数

在C#DllImport中使用32位或64位dll

这是情况,我在我的dot.net应用程序中使用基于C的dll.有2个dll,一个是32位称为MyDll32.dll,另一个是64位版本,名为MyDll64.dll.

有一个保存DLL文件名的静态变量:string DLL_FILE_NAME.

它以下列方式使用:

[DllImport(DLL_FILE_NAME, CallingConvention=CallingConvention.Cdecl, EntryPoint=Func1")]
private static extern int is_Func1(int var1, int var2);
Run Code Online (Sandbox Code Playgroud)

到目前为止简单.

可以想象,该软件是在打开"Any CPU"的情况下编译的.

我还有以下代码来确定系统是否应该使用64位文件或32位文件.

#if WIN64
        public const string DLL_FILE_NAME = "MyDll64.dll";
#else
        public const string DLL_FILE_NAME = "MyDll32.dll";        
#endif
Run Code Online (Sandbox Code Playgroud)

到目前为止,您应该看到问题.. DLL_FILE_NAME是在编译时定义的,而不是在执行时间中定义的,因此根据执行上下文不会加载右dll.

处理这个问题的正确方法是什么?我不想要两个执行文件(一个用于32位,另一个用于64位)?如何在DllImport语句中使用DLL_FILE_NAME 之前设置它?

.net c# pinvoke dllimport 32bit-64bit

59
推荐指数
4
解决办法
5万
查看次数

为什么Cdecl调用在"标准"P/Invoke公约中经常不匹配?

我正在开发一个相当大的代码库,其中C++函数是从C#调用P /.

我们的代码库中有很多调用,比如......

C++:

extern "C" int __stdcall InvokedFunction(int);
Run Code Online (Sandbox Code Playgroud)

使用相应的C#:

[DllImport("CPlusPlus.dll", ExactSpelling = true, SetLastError = true, CallingConvention = CallingConvention.Cdecl)]
    private static extern int InvokedFunction(IntPtr intArg);
Run Code Online (Sandbox Code Playgroud)

我已经搜索了网(在我有能力的范围内),因为为什么存在这种明显的不匹配.例如,为什么C#中有Cdecl,而C++中有__stdcall?显然,这会导致堆栈被清除两次,但是,在这两种情况下,变量都以相同的相反顺序被压入堆栈,这样我就不会看到任何错误,尽管在发生的情况下可能会清除返回信息.在调试期间尝试跟踪?

来自MSDN:http: //msdn.microsoft.com/en-us/library/2x8kf7zx%28v=vs.100%29.aspx

// explicit DLLImport needed here to use P/Invoke marshalling
[DllImport("msvcrt.dll", EntryPoint = "printf", CallingConvention = CallingConvention::Cdecl,  CharSet = CharSet::Ansi)]

// Implicit DLLImport specifying calling convention
extern "C" int __stdcall MessageBeep(int);
Run Code Online (Sandbox Code Playgroud)

再一次,extern "C"C++代码和CallingConvention.CdeclC#中都有.为什么不CallingConvention.Stdcall呢?或者,此外,为什么__stdcallC++中存在?

提前致谢!

c# c++ pinvoke cdecl stdcall

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

C#性能 - 使用不安全的指针而不是IntPtr和Marshal

我正在将C应用程序移植到C#中.C应用程序从第三方DLL调用许多函数,所以我在C#中为这些函数编写了P/Invoke包装器.其中的一些C函数分配,我有在C#应用程序使用的数据,所以就用IntPtr的,Marshal.PtrToStructure并且Marshal.Copy到本机数据(数组和结构)复制到管理变量.

不幸的是,C#app被证明比C版慢得多.快速的性能分析表明,上述基于编组的数据复制是瓶颈.我正在考虑通过重写它以使用指针来加速C#代码.由于我没有C#中不安全的代码和指针的经验,我需要有关以下问题的专家意见:

  1. 使用unsafe代码和指针而不是IntPtrMarshaling有什么缺点?例如,它是否以任何方式更不安全(双关语)?人们似乎更喜欢编组,但我不知道为什么.
  2. 使用P/Invoking指针真的比使用编组快吗?大约可以预期多少加速?我找不到任何基准测试.

示例代码

为了使情况更加清晰,我将一个小的示例代码(实际代码复杂得多)整合在一起.我希望这个例子说明我在谈论"不安全的代码和指针"与"IntPtr和Marshal"时的意思.

C库(DLL)

MyLib.h

#ifndef _MY_LIB_H_
#define _MY_LIB_H_

struct MyData 
{
  int length;
  unsigned char* bytes;
};

__declspec(dllexport) void CreateMyData(struct MyData** myData, int length);
__declspec(dllexport) void DestroyMyData(struct MyData* myData);

#endif // _MY_LIB_H_
Run Code Online (Sandbox Code Playgroud)

MyLib.c

#include <stdlib.h>
#include "MyLib.h"

void CreateMyData(struct MyData** myData, int length)
{
  int i;

  *myData = (struct MyData*)malloc(sizeof(struct MyData));
  if (*myData != NULL)
  {
    (*myData)->length = length; …
Run Code Online (Sandbox Code Playgroud)

c c# pinvoke unsafe marshalling

52
推荐指数
4
解决办法
3万
查看次数

PInvoke for C函数返回char*

我正在尝试编写一些从非托管DLL调用方法的C#代码.dll中函数的原型是:

extern "C" __declspec(dllexport) char *foo(void);
Run Code Online (Sandbox Code Playgroud)

在C#中,我首先使用:

[DllImport(_dllLocation)]
public static extern string foo();
Run Code Online (Sandbox Code Playgroud)

它似乎在表面上工作,但我在运行时遇到内存损坏错误.我想我指的是记忆恰好是正确的,但已经被释放了.

我尝试使用名为"P/Invoke Interop Assistant"的PInvoke代码生成实用程序.它给了我输出:

[System.Runtime.InteropServices.DLLImportAttribute(_dllLocation, EntryPoint = "foo")]
public static extern System.IntPtr foo();
Run Code Online (Sandbox Code Playgroud)

它是否正确?如果是这样,我如何将此IntPtr转换为C#中的字符串?

c# pinvoke

45
推荐指数
3
解决办法
2万
查看次数

对PInvoke函数'[...]'的调用使堆栈失衡

对于我已经使用了很长一段时间的一些东西,我得到了这个奇怪的错误.它可能是Visual Studio 2010中的新东西,但我不确定.
我试图用C#调用用C++编写的无人函数.
从我在互联网上阅读的内容和错误信息本身来看,这与我的C#文件中的签名与C++中的签名不同但我真的看不到它这一事实有关.
首先,这是我在下面的无人函数:

TEngine GCreateEngine(int width,int height,int depth,int deviceType);
Run Code Online (Sandbox Code Playgroud)

这是我在C#中的功能:

[DllImport("Engine.dll", EntryPoint = "GCreateEngine", CallingConvention = CallingConvention.StdCall)]  
        public static extern IntPtr CreateEngine(int width,int height,int depth,int device);
Run Code Online (Sandbox Code Playgroud)

当我调试到C++时,我看到所有的参数都很好,因此我只能认为它与从TEngine(这是一个名为CEngine的类的指针)转换为IntPtr有关.我之前在VS2008中使用过这个没问题.

c# c++ pinvoke unmanaged managed

45
推荐指数
4
解决办法
4万
查看次数

Win32 API函数以编程方式启用/禁用设备

我正在编写一个小型C#应用程序,以便在检测到其他鼠标设备时禁用设备(我的笔记本电脑触摸板),如果未检测到鼠标,则再次启用触摸板.我甚至无法在设备管理器中禁用触摸板(它在默认的鼠标类驱动程序上运行).

我正在进入设备驱动程序开发,所以我想也许我可以编写一个小的过滤器驱动程序,它只接受IOCTL来启用和禁用在设备堆栈上传递鼠标事件消息,并通过原始PDO从用户模式获取消息.但是,我问了这个问题,并且有人建议我可以通过SetupDi ..函数在usermode中执行此操作.这将是非常好的,因为这种原始的PDO通信方法是一个可以使用的PITA.

我以前只使用过SetupDiGetClassDevs,而且有很多这样的人,对于这部分Win32 API有更多经验的人可以快速告诉我应该调用什么来停止/禁用鼠标设备或其界面,或者是否有在框架的黑暗角落某处可以做到这一点(也许在WMI?).

更新(2009年9月24日)我想出了如何使用过滤器驱动程序执行此操作并发布了我在原始问题上的操作方式.我仍然想知道是否可以直接从Win32启用或禁用设备,如果可以,如何 - 所以我将打开这个问题.

.net c# windows pinvoke winapi

44
推荐指数
2
解决办法
6万
查看次数

有没有理由比CefGlue更喜欢CefSharp(反之亦然)?

在为.Net提供体面的Chromium Embedded Framework(CEF)实现方面,两个主要选项似乎是CefSharp和CefGlue.它们的方法不同(CefGlue使用P/Invoke调用CEF非托管代码,CefSharp使用围绕CEF库的混合模式C++/CLI包装器).

是否有某种原因混合模式汇编比P/Invoke调用更好?在所有其他条件相同的情况下,似乎CefGlue(P/Invoke lib)为CEF项目提供了一个"更薄"的包装器,这意味着响应上游库中的更新可能会更快.

那里有没有经验的两个图书馆谁可以分享差异化因素?

.net pinvoke webkit c++-cli chromium

44
推荐指数
4
解决办法
1万
查看次数

控制台应用程序中的全局热键

有谁知道如何在控制台应用程序中使用RegisterHotKey/UnregisterHotKey API调用?我假设设置/删除热键是相同的,但是如何在按下键时收到回叫?

我看到的每个例子都是针对Winforms和使用的protected override void WndProc(ref Message m){...},我无法使用.


更新:我的内容如下,但事件永远不会被击中.我认为这可能是因为当你加载ConsoleShell时它会阻止进一步的执行,但即使我放入SetupHotkey一个不同的线程也没有任何反应.有什么想法吗?

class Program
{
    static void Main(string[] args)
    {
        new Hud().Init(args);
    }
}

class Hud
{
    int keyHookId;


    public void Init(string[] args)
    {
        SetupHotkey();
        InitPowershell(args);
        Cleanup();
    }

    private void Cleanup()
    {
        HotKeyManager.UnregisterHotKey(keyHookId);
    }

    private void SetupHotkey()
    {
        keyHookId = HotKeyManager.RegisterHotKey(Keys.Oemtilde, KeyModifiers.Control);
        HotKeyManager.HotKeyPressed += new EventHandler<HotKeyEventArgs>(HotKeyManager_HotKeyPressed);
    }

    void HotKeyManager_HotKeyPressed(object sender, HotKeyEventArgs e)
    {
        //never executed
        System.IO.File.WriteAllText("c:\\keyPressed.txt", "Hotkey pressed");
    }

    private static void InitPowershell(string[] args)
    {
        var config = …
Run Code Online (Sandbox Code Playgroud)

c# pinvoke winapi console-application

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