c# 调用c库dll 遇到char*转string的解决办法

最近由于有个未知的设备需要用到modbus通讯协议,底层需要与PLC通讯,坤跌,PLC啥型号也不清楚封在里面不能拆,前人只留了几个不能运行的QT代码以及不完整的文档。用惯了C#想要重新学QT,真不知猴年马月能完成项目。于是乎找了一个开源的基于C语言开发的modbus库,撸起袖子干了起来。撸代码的过程中,遇到调用c 库的char*转c#的string多次不成功的情况,各种冒框啊,折腾了大半天才算解决,最终记录如下,以备后面遇到同样的坑能少走点弯路。

.h file

#pragma once
#define LineMaxLen 2048  
#define KeyMaxLen 128  
#define MaxFileLength 1024*10  
#if defined(_MSC_VER)
# if defined(DLLBUILD)
/* define DLLBUILD when building the DLL */
#  define MODBUS_API __declspec(dllexport)
# else
#  define MODBUS_API __declspec(dllimport)
# endif
#else
# define MODBUS_API
#endif

static char value[KeyMaxLen];//需要定义为全局变量,编译成dll后才能被c#正常调用,否则指针地址有数据,指针内容看到的返回值为空

MODBUS_API char* getValue();
MODBUS_API int sum(int a, int b);

#endif  

.c file

char* getValue()//char key[KeyMaxLen]
{			
	memset(value, 0, sizeof(value));
	strcpy(value, "abcdefgh");
	return  value;
}

.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace RotPlatformControl_CsDll
{
    public class CRotPlatformControl
    {
        [DllImport("modbus.dll", EntryPoint = "getValue", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
        public static extern IntPtr getValue();//不能用string,使用IntPtr对应于c中的函数返回类型char*
        
    }
}
private void buttonHome_Click(object sender, EventArgs e)
        {           
            IntPtr temp = CRotPlatformControl.getValue();
            res=Marshal.PtrToStringAnsi(temp).ToString();
            temp = IntPtr.Zero;

            lblMessage.Text = res.ToString();
        }
UI显示“abcdefgh” 说明dll已经调用成功。



总结:

1. const char* 直接换成string

2. char*做形参或返回值,需要换成IntPtr

3. char*做形参并想要获取char*内容,使用ref IntPtr无用。只能将该char*改为返回值获得。

4. C库文件中需要定义为全局变量,编译成dll后才能被c#正常调用,否则指针地址有数据,指针内容看到的返回值为空。


modbus封库源码

https://download.csdn.net/download/ericwuhk/10352801



阅读更多

没有更多推荐了,返回首页