C#引用C++开发的DLL

.Net 开发中如果使用外部DLL,一般引用进来就可以了,最多引用前将DLL注册一下。最近做的项目中需要使用硬件厂家用C++开发的DLL,我还照原来的方式引用却报错,一步步用下来却发现原来还有这么多技巧需注意。下面是我所遇到的问题及解决的方法,希望能对大家有用。

1.在Visual Studio中引用C++写的DLL时报以下错误:

未能添加引用,请确保此文件可访问并且是一个有效的程序集或COM组件。

手工注册该DLL也报错:模块已加载,但找不到入口点DLLRegisterServer, 请确保XXX为有效的DLL或OCA文件,然后重试。

经查询发现C++编译的DLL并不一定能被C#直接使用,需通过C#中的DllImport直接调用这些功能。

代码如下所示:

在程序开始时使用以下语句注册方法。

[DllImport("Enc7481.dll", EntryPoint = "_Enc7481_Set_Encoder", ExactSpelling = false, CallingConvention = CallingConvention.StdCall)]
 private extern static void _Enc7481_Set_Encoder(UInt16 intDirection, Int32 lngValue);

在程序中直接调用就可以了:

_Enc7481_Set_Encoder(0, 0);

2.找不到对应的方法

使用以上的程序后,参考厂商所给的C++程序却报找不到对应的入口点,也就是函数名称不对。C++DLL编译后函数名称会有变化,需使用eXeScope.exe查询具体的函数名称。

3.报内存错误:

尝试读取或写入受保护的内存。这通常指示其他内存已损坏。造成这种错误的情况很多,一般来说是对函数的使用错误造成的。对于我的程序来说是因为需要首先调用_Enc7481_Init()来初始化。

4.类型错误

终于将以上错误都解决,程序可以运行了,但发现取到的数据总是不对,再次检查,发现原来是数据类型不对造成的。

VC++中主要字符串类型为:LPSTR,LPCSTR, LPCTSTR, string, CString, LPCWSTR, LPWSTR等
但转为C#类型却不完全相同,只有数据类型对应正确才能取得正确的数据。

类型对照:

BSTR ---------  StringBuilder

LPCTSTR --------- StringBuilder

LPCWSTR ---------  IntPtr

handle---------IntPtr

hwnd-----------IntPtr

char *----------string

int * -----------ref int

int &-----------ref int

void *----------IntPtr

unsigned char *-----ref byte

5.结构体参数的传递

对于结构体参数需要在C#中建立对应的结构体,并用Marshal类将结构体转换为指针地址传给C++函数,取得数据后再根据指针地址取得对应的结构。

HREE structThree = new THREE();
            IntPtr ptrThree = Marshal.AllocHGlobal(Marshal.SizeOf(structThree));
            Marshal.StructureToPtr(structThree, ptrThree, false);
            _Enc7481_Get_ThreeEncoder2(ptrThree);
            structThree = (THREE)Marshal.PtrToStructure(ptrThree, typeof(THREE));

时间: 2024-09-28 06:37:14

C#引用C++开发的DLL的相关文章

C#开发模式——dll多级引用的问题

C#解决方案里有两种引用方式,项目引用和dll物理文件引用. 一.项目引用 严格引用,项目文件需包含在解决方案里,好处是便于调试,可直接进入代码.缺点是耦合度太高(必须全部编译通过才能run起来),项目太大的话编译麻烦,不利于部署升级和测试.因为是严格引用,单独替换dll是不起作用的.而且每次升级程序都要重新编译.打包.卸载.安装,相当麻烦. 二.dll物理文件引用 松散引用,引用的是dll物理文件,dll项目包不包含在解决方案里都无所谓(一般是包含的),好处是不必全部重新编译,哪里修改编译哪里

C++如何调用C#开发的dll

序言 本文介绍一个C++如何调用C#开发的dll实例. 前言 C++编写的程序为非托管代码,C#编写的程序为托管代码.托管代码虽然提供了其他开发平台没有的许多优势,但由于前期系统及历史版本很多使用的是非托管代码编写的程序,所以CLR提供了一些机制,允许在应用程序中同时包含托管和非托管代码.具体说分为以下三种: 托管代码能调用DLL中的非托管函数.通过P/Invoke(Platform Invoke)机制调用DLL中的函数,如Kernel32.dll等. 托管代码可以使用现有COM组件(服务器).

通过c#去调用c++开发的dll com 组件 -Import com

这个问题缠了我2个小时才弄出来,其实很简单.当对方提供一个dll给你使用时,你需要去了解这个dll 是由什么语言写的,怎么编译的,看它的编译类型.这样即使在没有头绪时,你可以先尝使用一些比较热门的编译工具去解析它.比如gcc,reflector,ILSpy 都行. 关于C++写出来的dll,理论上也是一个dll,但更准确定义应该称为是一个特殊的dll.普通的dll,比如NOPI.DLL,我们只需要在项目中去引用它再加个namespace就可以去使用它内部提供的方法.而c++编译出来的dll 则需

cad.net WPF的MarkupExtension接口引用问题,System.Xaml.dll的引用问题

很不幸的是,在cad上面敲WPF的话,您无可避免地需要将工程设置成 .NET standard 项目, 因为WPF需要判断不同的 net 版本,而传统的 .NET Framework 无法判断.... 而很幸福的是,不需要改代码,只需要学习写.csporj文件就可以了...这相当于写一个xml吧... 而我们为什么要判断 net 版本呢?因为写 WPF 存在一个版本差,这个版本差分别是低版本的 net3.5 和高版本的 net4.0, 因为 net4.0 写了很多很丰富的函数..... 而WPF

在Visual Studio开发的项目中引用GAC中的dll

Open the windows Run dialog (Windows Key + r) Type C:\Windows\assembly\gac_msil. This is some sort of weird hack that lets you browse your GAC. You can only get to it through the run dialog. Find your assembly and copy its path from the address bar.

Winform中DockPanel(引用WeifenLuo.WinFormsUI.Docking.dll组件)的使用

WeiFenLuo.WinFormsUI.Docking.dll是开源项目DockPanel Suite的一个类库,可实现像Visual Studio的窗口停靠.拖拽等功能.WeifenLuo.WinFormsUI.Docking是一个很强大的界面布局控件,可以保存自定义的布局为XML文件,可以加载XML配置文件.DockPanel中提供了几个可用的类,重要的有两个:DockPanel和DockContent.DockPanel是从Panel继承出来的,用于为可浮动的dock的子窗口提供进行浮动

Visual Studio使用技巧笔记(引用程序集自动复制dll到引用项目目录)

copy /y $(TargetPath) $(SolutionDir)\[您项目引用dll文件的目录]\$(TargetFileName) 例如:copy /y $(TargetPath) $(SolutionDir)\Dynamic.CallEntryTests\dlls\$(TargetFileName)

[原创]C#引用C++编译的dll

一.DllImportAttribute 1.属性介绍 1 using System; 2 using System.Reflection; 3 using System.Security; 4 5 namespace System.Runtime.InteropServices 6 { 7 // Summary: 8 // Indicates that the attributed method is exposed by an unmanaged dynamic-link 9 // libr

vs2015 引用lib库和dll

1.首先右键项目->属性 2.在项目中添加lib文件夹,把lib库放在文件夹下面,然后在图中的库目录引用当前路径的lib文件夹 3.在项目的路径下添加include中添加头文件,然后在常规中添加附加包含目录 4.在链接器->输入->附加依赖项添加具体的lib库 5.最后把dll放在项目的路径下即可