libmodbus-3.1.6 linux编译动态/静态链接库,并在c++下使用
既然想到这个库了,那自然应该都清楚其来历和用途了,本文就不再做过多介绍了。本文主要讲解如何将libmodbus-3.1.6源码编译成动态或者静态链接库,以便在项目中使用。
1.源码下载
下载地址:https://github.com/stephane/libmodbus
2.源码提取
解下下载的源码包,创建一个文件夹,文件夹命明随意,将源码包中的src目录下的 .h 和 .c 文件全部拷贝到刚创建的文件夹下,如下图所示:
当然,嫌麻烦可以去下载我整理好的编译包https://download.csdn.net/download/sf877/88632947
3.编写makefile
在上面创建的目录中新建一个Makefile文件,Makefile内容如下:
TOOL = x86_64
# TOOL = aarch64
ifeq ($(TOOL), aarch64)
CC = aarch64-linux-gnu-gcc
AR = aarch64-linux-gnu-ar
LIB_PATH = ./lib_aarch64
else
ifeq ($(TOOL), x86_64)
CC = gcc
AR = ar
LIB_PATH = ./lib_x86_64
endif
endif
SRC = $(shell find -name '*.c') #查找目录下所有c文件
OBJS = $(SRC:.c=.o) #把.c变成.o
STATIC_LIB = libmodbus.a
SHARE_LIB = libmodbus.so
INSTALL_PATH = libmodbus
ARFLAGS = -rc
LDFLAGS = -shared -fpic
$(warning program is being complied. the PLATFORM is $(PLATFORM))
all : $(STATIC_LIB) $(SHARE_LIB)
$(STATIC_LIB) : $(OBJS)
$(AR) $(ARFLAGS) -o $(STATIC_LIB) $(OBJS)
$(SHARE_LIB) : $(OBJS)
$(CC) $(LDFLAGS) -o $(SHARE_LIB) $(SRC)
.PHONY: install
install:
mkdir -p $(INSTALL_PATH)/include/
mkdir -p $(INSTALL_PATH)/$(LIB_PATH)/
cp $(STATIC_LIB) $(INSTALL_PATH)/$(LIB_PATH)/
cp $(SHARE_LIB) $(INSTALL_PATH)/$(LIB_PATH)/
cp *.h $(INSTALL_PATH)/include/
.PHONY: clean
clean:
rm -f *.o
rm -f *.a
rm -f *.so
rm -rf ./$(INSTALL_PATH)
.PHONY: test
test:
cp $(STATIC_LIB) ./Test/lib/
cp $(SHARE_LIB) ./Test/lib/
cp *.h ./Test/include/
我这里是带了交叉编译环境,如果有交叉编译需要,可以将交叉编译环境改为自己的即可。
4.编译库
新建终端,cd 进入该目录,输入:
make
即可同时编译出动态链接库和静态链接库;
5.编写从站测试
如果直接用我上面的makefile写法,只需要输入make test
即可自动生成一个 Test 目录,在Tese目录中新建一个 main.cpp 文件,测试代码代码如下(注意修改ip和端口号):
main.cpp
#include <iostream>
#include <string>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
extern "C" {
#include <modbus.h>
}
#define ADDRESS_START 0 //读寄存器起始地址
#define ADDRESS_END 50 //读寄存器结束地址
#define WRITE_START 2 //写寄存器起始地址
#define WRITE_END 12 //写寄存器结束地址
int main()
{
modbus_t* ModbusTcp;
uint16_t tab_reg[100];
memset(tab_reg, 0, sizeof(tab_reg));
uint16_t tab_write[100];
memset(tab_write, 0, sizeof(tab_write));
ModbusTcp = modbus_new_tcp("66.66.66.1", 15000);
if (NULL == ModbusTcp)
{
fprintf(stderr, "Error: %s\n", modbus_strerror(errno));
return 1;
}
else
{
printf("设置TCP成功\n");
}
// modbus_set_debug(ModbusTcp, true); //设置为调试模式,会打印相关通信数据
int ret = modbus_connect(ModbusTcp); //连接从站
if (-1 == ret)
{
fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
modbus_free(ModbusTcp);
return 1;
}
uint16_t index = 0;
unsigned char buff[1024];
memset(buff, 0, sizeof(buff));
while(ModbusTcp != NULL)
{
int res = modbus_read_registers(ModbusTcp, ADDRESS_START, ADDRESS_END, tab_reg); //从地址0开始,读取50个线圈
std::cout << "Read res = " << res << std::endl;
if(res > 0)
{
for(int i=0; i<res; i++)
{
printf("%.4X ", tab_reg[i]);
// buff[i*2] = tab_reg[i] >> 8;
// buff[1 + i*2] = tab_reg[i];
}
printf("\n");
// memcpy(buff, tab_reg, res*2);
// unsigned short tt = 0;
// memcpy(&tt, &buff[2], sizeof(tt));
// for(int i=0; i<res*2; i++)
// {
// printf("%.2X ", buff[i]);
// }
// printf(",\t tt = %d\n", tt);
}
usleep(500 * 1000);
for(int i=0; i<(WRITE_END-WRITE_START); i++)
{
tab_write[i] = index + i;
}
ret = modbus_write_registers(ModbusTcp, WRITE_START, WRITE_END, tab_write);
if (WRITE_END != ret)
{
printf("Error modbus_write_bit: %d\n", ret);
printf("WRITE_START: %d WRITE_END: %d\n", WRITE_START, WRITE_END);
}
else
{
printf("modbus_write_registers() OK, index = %d\n", index);
index += 1;
}
usleep(500 * 1000);
}
modbus_close(ModbusTcp);
modbus_free(ModbusTcp);
std::cout << "=====================================" << std::endl;
return 0;
}
当然还需要编译测试工程所需要的 makefile,在Test目录下再新建一个makefile文件,内容如下:
makefile
CCC=g++
OUTPUT = run
CXXFLAGS = -std=c++11 -Wall
INC_PATH = -I./include
LIBS = lib/libmodbus.so
SRC_CPP = $(shell find -name '*.cpp') #查找目录下所有cpp文件
OBJS_CPP = main.o #$(SRC_CPP:.cpp=.o) #把.cpp变成.o
$(OUTPUT): $(OBJS_CPP)
$(CCC) $(OBJS_CPP) $(LIBS) -lm -lpthread -o $(OUTPUT)
%.o : %.cpp
$(CXX) $(INC_PATH) -c -o $@ $^ $(CXXFLAGS)
.PHONY:clean
clean:
rm $(OBJS_CPP)
rm $(OUTPUT)
接下来就可以编译测试工程进行测试了,这里配合测试的工具是Mbslave,正常会看到如下打印信息: