类别:程序开发

日期:2022-09-23 浏览:1819 评论:0

最近调用动态库传数据,发现C#接收C++动态库返回字符串char*,在C#端设置对应类型为string无法接收到正确值,最后想到在C#端先用字节数组接收返回的字符串,然后再将字节数组转换为对应的字符串,数据接收终于正确

首先打开VS2012,新建项目->Visual C++,选择Win32项目,如图选择dll

86e75f3ccb3c4a5e97f0519fe451ed2f.png

新建项目的名字为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.csdn.net/cry_smile_hate/article/details/103695020?spm=1035.2023.3001.6557&utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-2defaultOPENSEARCHdefault-1.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-2defaultOPENSEARCHdefault-1.nonecase

https://blog.csdn.net/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);
        }
    }
}

dc62a3f443234106ac98794ed46e6084.png




本文标题:C#接收C++动态库返回字符串char*,在C#端如何接收并得到正确的字符串
本文链接:https://vtzw.com/post/1058.html
作者授权:除特别说明外,本文由 零一 原创编译并授权 零一的世界 刊载发布。
版权声明:本文不使用任何协议授权,您可以任何形式自由转载或使用。
 您阅读本篇文章共花了: 

 可能感兴趣的文章

评论区

发表评论 / 取消回复

必填

选填

选填

◎欢迎讨论,请在这里发表您的看法及观点。