相关文章推荐
讲道义的砖头  ·  c++ convert int to ...·  1 年前    · 
谦和的猕猴桃  ·  Kaggle ...·  1 年前    · 

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&quot;Str_Output %s\n&quot;, 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.
楼主,按照你的方式搭建好认证中心,网关跳转认证中心获取token时,抛出这个:{ "error": "invalid_client", "error_description": "Bad client credentials" },这是啥原因 PowerDesigner Model Properties 没有Database菜单/选项 Ealser: PDM模型有database,CDM模型没有。 关于Dll中“没有可放置在工具箱的组件”的解决方案 gtclulong: 2019也能用了! 简单粗暴啊.... 楼主好厉害,这么生猛的方法都能试出来表情包