最近调用动态库传数据,发现C#接收C++动态库返回字符串char*,在C#端设置对应类型为string无法接收到正确值,最后想到在C#端先用字节数组接收返回的字符串,然后再将字节数组转换为对应的字符串,数据接收终于正确
首先打开VS2012,新建项目->Visual C++,选择Win32项目,如图选择dll
新建项目的名字为dlltest,新建头文件dlltest.h,在源文件dlltest.cpp中加入如下代码:
#include "stdafx.h"
#include "dlltest.h"
char s[20]="您好hahaha";
int __stdcall test(char* str)
{
char attr[1024];
memset(attr,0,sizeof(attr));
memcpy(attr,s,sizeof(s));
memcpy(str,attr,sizeof(attr));
return 1;
}
在dlltest.h中加入:
extern "C" _declspec(dllexport) int __stdcall test(char* str);
运行环境为debug模式,点击生成解决方案,在debug文件下可看到生成了dlltest.dll,这就是动态库文件。
打开VS2012,新建Visual C#控制台应用程序,命名为dlltestC
新建类文件Class1.cs,启动程序,运行空项目(debug模式),生成exe文件,打开exe所在目录,将之前生成的dll复制到该目录下,如图
然后在Class1.cs中加入如下代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace dlltestC
{
public class Class1
{
[DllImport("dlltest.dll", EntryPoint = "test")]
public extern static int test(ref byte str);
}
}
最后在Program.cs中加入:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace dlltestC
{
public class Program
{
static void Main(string[] args)
{
byte[] s = new byte[1024];
int t = Class1.test(ref s[0]);//用字节数组接收动态库传过来的字符串
string strGet = System.Text.Encoding.Default.GetString(s, 0, s.Length); //将字节数组转换为字符串
Console.WriteLine(strGet);
}
}
}
运行该程序,输出:您好hahaha
参考网址 :
https://blog.youkuaiyun.com/qq_22889875/article/details/78670172
// CDLLDemo.cpp : 定义 DLL 应用程序的导出函数。
//
#include "stdafx.h"
#include "string.h"
#include <stdio.h>
#include <time.h>
extern "C" __declspec(dllexport)
int ParseBaliseMsg2(const unsigned char *pMsgData, char *resTgm, char *resStr)
{
/*CString strInfo;
strcpy(resTgm, strMsg.GetBuffer());
strMsg = strFor1 + strMsg + strFor2;
strInfo += "erro!!!";
strcpy(resStr, strInfo.GetBuffer());*/
//memset(resStr, 0, 50);
printf("%s \r\n", pMsgData);
char *a = "ParseBaliseMsg2 hello word!";
strcpy(resStr, a);
printf("resStr is: %s \r\n", resStr);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("The current date/time is: %s \r\n", asctime(timeinfo));
return 120;
}
extern "C" __declspec(dllexport)
char * ParseBaliseMsg3(const unsigned char *pMsgData, char *resTgm, int & retInt)
{
/*CString strInfo;
strcpy(resTgm, strMsg.GetBuffer());
strMsg = strFor1 + strMsg + strFor2;
strInfo += "erro!!!";
strcpy(resStr, strInfo.GetBuffer());*/
//memset(resStr, 0, 50);
printf("%s \r\n", pMsgData);
char *resStr = "ParseBaliseMsg3 hello word!";
printf("resStr is: %s \r\n", resStr);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("The current date/time is: %s \r\n", asctime(timeinfo));
retInt = 130;
return resStr;
}
extern "C" __declspec(dllexport)
int ParseBaliseMsg4(const unsigned char *pMsgData, char *resTgm, char *resStr)
{
/*CString strInfo;
strcpy(resTgm, strMsg.GetBuffer());
strMsg = strFor1 + strMsg + strFor2;
strInfo += "erro!!!";
strcpy(resStr, strInfo.GetBuffer());*/
//memset(resStr, 0, 50);
printf("%s \r\n", pMsgData);
char *a = "ParseBaliseMsg4 hello word!";
strcpy(resStr, a);
printf("resStr is: %s \r\n", resStr);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("The current date/time is: %s \r\n", asctime(timeinfo));
return 140;
}
extern "C" __declspec(dllexport)
int ParseBaliseMsg5(const unsigned char *pMsgData, char *resTgm, char *resStr)
{
/*CString strInfo;
strcpy(resTgm, strMsg.GetBuffer());
strMsg = strFor1 + strMsg + strFor2;
strInfo += "erro!!!";
strcpy(resStr, strInfo.GetBuffer());*/
//memset(resStr, 0, 50);
printf("%s \r\n", pMsgData);
char *a = "ParseBaliseMsg5 hello word!";
strcpy(resStr, a);
printf("resStr is: %s \r\n", resStr);
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("The current date/time is: %s \r\n", asctime(timeinfo));
return 150;
}
extern "C" __declspec(dllexport)
char* strcpyTest(char* dest, char* sour)
{
char* temp = dest;
while ('\0' != *sour)
{
*dest = *sour;
dest++;
sour++;
}
*dest = '\0';
return temp;
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
namespace DotNet_Use_C_Demo
{
public class TestCMethodHelper
{
[DllImport("CDLLDemo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern int ParseBaliseMsg2(string msg, string rmsg, ref byte memory);
[DllImport("CDLLDemo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern IntPtr ParseBaliseMsg3(string msg, string rmsg, ref int rInt);
[DllImport("CDLLDemo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern IntPtr ParseBaliseMsg4(string msg, string rmsg, [MarshalAs(UnmanagedType.LPStr)]StringBuilder t);
[DllImport("CDLLDemo.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private static extern IntPtr ParseBaliseMsg5([MarshalAs(UnmanagedType.LPStr)]StringBuilder msg, string rmsg, [MarshalAs(UnmanagedType.LPStr)]StringBuilder t);
[DllImport("CDLLDemo.dll", EntryPoint = "strcpyTest", CallingConvention = CallingConvention.Cdecl/*, CallingConvention = CallingConvention.Cdecl*/)]
public static extern IntPtr strcpyTest(ref byte destA, string sourA);
public static void TestMethod()
{
Byte[] bPara = new Byte[100]; //新建字节数组
var r2 = ParseBaliseMsg2("abcd", "", ref bPara[0]);
string strGet = System.Text.Encoding.Default.GetString(bPara, 0, bPara.Length); //将字节数组转换为字符串
Console.WriteLine("返回值:" + r2);
Console.WriteLine("传出值:" + strGet);
Console.WriteLine("***************************************************");
int retResult = 0;
IntPtr pRet = ParseBaliseMsg3("1234", "", ref retResult);
string strRet = Marshal.PtrToStringAnsi(pRet);
Console.WriteLine("返回值:" + strRet);
Console.WriteLine("传出值:" + retResult);
Console.WriteLine("***************************************************");
//StringBuilder方式
StringBuilder sb = new StringBuilder();
var r4 = ParseBaliseMsg4("abcd", "", sb);
Console.WriteLine("返回值:" + r4);
Console.WriteLine("传出值:" + sb.ToString());
Console.WriteLine("***************************************************");
StringBuilder sb5 = new StringBuilder();
StringBuilder sb5E_para = new StringBuilder();
sb5E_para.Append("abcdedf123456");
var r5 = ParseBaliseMsg5(sb5E_para, "", sb5);
Console.WriteLine("返回值:" + r5);
Console.WriteLine("传出值:" + sb5.ToString());
}
public static void CpyTest()
{
string strSour = "测试调用C++ dll";
Byte[] bPara = new Byte[100]; //新建字节数组
IntPtr pRet = strcpyTest(ref bPara[0], strSour);
string strGet = System.Text.Encoding.Default.GetString(bPara, 0, bPara.Length); //将字节数组转换为字符串
string strRet = Marshal.PtrToStringAnsi(pRet);
Console.WriteLine("源字符串:");
Console.WriteLine(strSour);
Console.WriteLine("传出值:");
Console.WriteLine(strGet);
Console.WriteLine("返回值:");
Console.WriteLine(strRet);
}
}
}