C#调用C++ 平台调用P/Invoke 函数指针/回调函数【二】
C#调用C++ 平台调用P/Invoke 字符串【三】
C#调用C++ 平台调用P/Invoke 错误码LastError【四】
C#调用C++ 平台调用P/Invoke 结构体--输入输出参数、返回值、返出值、结构体数组作为参数【五】
C#调用C++ 平台调用P/Invoke 结构体--含有内置数据类型的一维、二维数组、字符串指针【六】
C#调用C++ 平台调用P/Invoke 结构体--内存对齐方式、union封装【七】
C#调用C++ 平台调用P/Invoke 结构体--结构体嵌套【八】
【1】字符串作为输入参数
C++代码:
EXPORTDLL_API int Str_Output( WCHAR *pStr )
if (NULL == pStr)
return(-1);
wprintf(L"Str_Output %s\n", pStr);
return(0);
C#代码,定义成string即可:
[DllImport("ExportDll.dll", CharSet=CharSet.Unicode)]
public static extern int Str_Output([MarshalAs(UnmanagedType.LPWStr)]string pStr);
string str = "hjkl;";
CExportDll.Str_Output(str);
【2】字符串作为参数,需要进行修改返回
C++代码:
EXPORTDLL_API int Str_Change( WCHAR *pStr, int len )
if (NULL == pStr)
return(-1);
for (int ix=0; ix<len-1; ix++)
pStr[ix] = 'a' + (ix) % 26;
pStr[len-1] = '\0\0';
wprintf(L"Str_Change %s\n", pStr);
return(0);
C#代码,定义成stringBuilder类型
[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]
public static extern int Str_Change([MarshalAs(UnmanagedType.LPWStr)]StringBuilder pStr, int len);
StringBuilder strBuilder = new StringBuilder(256);
CExportDll.Str_Change(strBuilder, 256);
【3】字符串作为返回值
C++代码:
static WCHAR *g_StrReturn = L"Str_Return";
EXPORTDLL_API WCHAR * Str_Return()
wprintf(L"Str_Return \n");
return(g_StrReturn);
C#代码,将返回值定义成IntPtr,再进行解析:
[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr Str_Return();
IntPtr strPtr = CExportDll.Str_Return();
string strIntPtr = Marshal.PtrToStringUni(strPtr);
【4】字符串数组作为参数,每个元素长度为10
C++代码:
EXPORTDLL_API int Str_ChangeArr( WCHAR **ppStr, int len )
if (NULL == ppStr)
return(-1);
for (int ix=0; ix<len; ix++)
if (NULL != ppStr[ix])
lstrcpyn(ppStr[ix], L"abc", 10);
wprintf(L"Str_ChangeArr \n");
return(0);
C#代码,定义成string[],如果数据需要返出,还必须指定In、Out参数:
[DllImport("ExportDll.dll", CharSet = CharSet.Unicode)]
public static extern int Str_ChangeArr([In, Out]string[] ppStr, int len);
string[] strArr = new string[4] {new string('\0', 10),
new string('\0', 10),
new string('\0', 10),
new string('\0', 10) };
CExportDll.Str_ChangeArr(strArr, 4);
【5】释放非托管的内存
C++代码:
EXPORTDLL_API void Str_ParameterOut( WCHAR **ppStr )
if (NULL == ppStr)
return;
*ppStr = (WCHAR *)CoTaskMemAlloc(128 * sizeof(WCHAR));
lstrcpynW(*ppStr, L"abc", 128);
wprintf(L"Str_ReturnOut \n");
C#代码,此时可以使用两种方式:
自动释放内存,必须使用string接受:
//使用CoTaskMemAlloc方法申请的内存,则会自动调用CoTaskMemFree来释放非托管内存
//这就意味了托管代码无需处理内存问题,减轻了托管代码的的复杂度
//但.NET只能释放由CoTaskMemAlloc分配的内存,所以如果底层不是使用CoTaskMemAlloc申请的内存,必须定义对应的释放函数
[DllImport("ExportDll.dll", CharSet = CharSet.Unicode, EntryPoint = "Str_ParameterOut")]
手动释放内存:
//使用IntPtr接受时,需要手动释放
[DllImport("ExportDll.dll", CharSet = CharSet.Unicode, EntryPoint = "Str_ParameterOut")]
public static extern void Str_ParameterOuttPtr(ref IntPtr ppStr);
string strOut = "";
CExportDll.Str_ParameterOutString(ref strOut);
//手动释放
IntPtr strOutIntPtr = IntPtr.Zero;
CExportDll.Str_ParameterOuttPtr(ref strOutIntPtr);
string strOut2 = Marshal.PtrToStringUni(strOutIntPtr);
Marshal.FreeCoTaskMem(strOutIntPtr);
Git p-invoke 源码地址【1】字符串作为输入参数C++代码:EXPORTDLL_API int Str_Output( WCHAR *pStr ){ if (NULL == pStr) { return(-1); } wprintf(L"Str_Output %s\n", pStr); return(0);}C#代码,定义成string即可:...
可以说新手使用P-INVOKE最开始的头疼就是C#和C++的字符串传递,因为这里涉及到两个问题。
第一:C#的string和C++的字符串首指针如何对应。
第二:字符串还有ANSI和UNICODE(宽字符串)之分。
本文分三部分阐述:
第一:字符串指针当输入参数,
第二:字符串指针作为返回值,
第三:字符串指针作为输入输出参数。
C++部分的测试代码很简单这里就全部贴出来...
C#调用 非托管C++ dll 传入Stringbuilder、ref string 、 ref char 等都报错,如mscorlib.dll 异常、其他信息: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏 等等
后来看到文章提到byte,想起来之前调用没有问题是用的byte,C#中的char是两个字节,用byte能证明标识内存地址
http://msdn.microsoft
在网上看到很多网友在.NET程序中调用Win32 API,或者调用自己的VC DLL里面提供的函数的时候,总是被生成正确的C函数在C#中的正确声明而困扰,而生成C++中结构体在C#中的声明 - 天,没有什么比这个更让人恶心的事情了。因为:
1. 如果你的结构体里面包含 TCHAR字符串成员的话,需要考虑ANSI和Unicode DLL的情形。
2. 如果你的结构体里面包含数组成员,需要考虑定长...
(译注:P/Invoke,全称是platform invoke service,平台调用服务,简单的说就是允许托管代码调用在 DLL 中实现的非托管函数。而在这期间一个重要的工作就是marshall:让托管代码中的数据和原生代码中的数据可以相互访问。我在下文中都称之为内存转换。)
这是IL2CPP深入讲解的第六篇。在这篇文章里,我们会讨论il2cpp.exe是如何生成在托管代码和原生代码间进行交
本篇文章是对c++中的char*与wchar_t*与string以及wstring之间的相互转换进行了详细的分析介绍,需要的朋友参考下#ifndefUSE_H_
#defineUSE_H_
#include<iostream>
#include<windows.h>
#include<s...
目录导航一:背景二:PInvoke互操作技术1. 一些前置基础2. 基本类型的互操作2. 字符串的互操作3. 复杂类型的处理4. 回调函数(异步)的处理三:总结
如果你常翻看FCL的源码,你会发现这里面有不少方法借助了C/C++的力量让C#更快更强悍,如下所示:
[DllImport("QCall", CharSet = CharSet.Unicode)]
[SecurityCritical]
[SuppressUnmanagedCodeSecurity]
一、P/Invoke Instruction:
Link: An Introduction to P/Invoke and Marshaling on the Microsoft .NET Compact Framework
P/Invoke, or Pinvoke stands for Platform Invocation Services. PI
最近做项目的时候,需要对接厂商提供的 IP 摄像头。但是他们只提供了 C++ 的 SDK,没办法,只能开始撸 C# 的 SDK Helper 类。本篇文章主要记录了对接 C++ DLL 需要注意的几个地方,以及常见类型的转换。
要对接 C++ 的 DLL,首先得知道如何引用 DLL 内的方法。在 C# 当中,只需要编写符合 C++ 的函数签名,再使用[DllImport]特性指定 DLL 文件路径和入口点等参数即可。
假如你需要使用 Win32 API 提供的方法,这里我以SetProcessDP...
C# P/Invoke中传递数组参数
C#在调用动态库接口,有时需要在C#中分配非托管内存,以便动态库可以写入返回的数据;有时我们需要传递一个复杂的数组等等。在C++的方法原型中,是一个*即指针,在C#的方法原型,相对应的可以是IntPtr,有些也可以直接使用[Out,In]等属性。
对于基础数组的数组,可以使用
Byte[] photoData = new Byte[CompressPhotoSize];
GCHandle gh = GCHa...
在C#中调用C或者C++的DLL一直是一个让我很头痛的问题,在网上查了很多资料仍然没有研究透彻,终于有一天,发现了这个工具,除了完美我找不出其他的词语来形容。
原文地址:http://blog.csdn.net/donjuan/article/details/3865026
太喜欢这个工具了
另外还有一个微软官方帮助P/Invoke的小工具
原文地址:http://www.cnblogs.
PowerDesigner Model Properties 没有Database菜单/选项
Ealser:
关于Dll中“没有可放置在工具箱的组件”的解决方案
gtclulong: