C# calls the c library dll and encounters a solution to char* to string

Recently, due to an unknown device that needs to use the modbus communication protocol, the bottom layer needs to communicate with the PLC. Kundi, the PLC model is not clear, it is sealed inside and cannot be disassembled. The predecessors only left a few QT codes that could not be run and incomplete. 's documentation. I'm used to C# and want to learn QT again, but I really don't know if I can complete the project in the year of the monkey. So I found an open source modbus library based on C language, rolled up my sleeves and started working. In the process of writing the code, I encountered a situation where calling the char* of the c library to the string of c# was unsuccessful many times, all kinds of frames, and it took a long time to solve it. The final record is as follows, in case the same pit is encountered in the future. Take less detours.

.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];//It needs to be defined as a global variable, and it can be called normally by c# after compiling into dll, otherwise the pointer address has data, and the return value seen by the pointer content is empty

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();//You cannot use string, use IntPtr to correspond to the function return type in 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();
        }
The UI displays "abcdefgh", indicating that the dll has been successfully called.



Summarize:

1. const char* is directly replaced by string

2. When char* is used as a formal parameter or return value, it needs to be replaced by IntPtr

3. When char* is used as a formal parameter and you want to get the content of char*, it is useless to use ref IntPtr. It can only be obtained by changing the char* to the return value.

4. The C library file needs to be defined as a global variable, and it can be called normally by c# after it is compiled into a dll. Otherwise, the pointer address has data, and the return value seen by the pointer content is empty.


modbus sealed library source code

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



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324537273&siteId=291194637