Linux下代码移植及混合编程
2018-02-12 12:28
459 查看
Windows下udp编程
Linux下C编程
makefile
udp程序移植到Linux
cc 混合编程so库文件的编写
混合编程头文件编写
so库的编写
QT项目下,在profile中需要添加lib,用于链接
LIBS += -l ws2_32
### 编译库文件的makefile
### 链接库文件的应用的makefile
Linux和Windows在使用udp编程上的差异(移植关键)主要有:
SOCKET类型是windows定义,linux下为int类型
由于历史原因,windows对于udp的支持为外挂形式,需要手动启动资源、关闭资源,linux无须,可用宏解决该问题
关闭socket的函数不同,windows下为closesocket(SOCKET),linux下为close(int)
htons函数头文件不同,linux下可用man查看该函数头文件,包括查看socket相关头文件。
win下需要头文件
C++函数具有继承重载等面向对象特性,在预编译时,预编译器对函数名有处理,而C的函数在预编译时函数名不会做改变(通过编译器 -E选项可以看到结果)。所以.cpp文件调用a.c文件的函数会出现函数未定义的情况,此时可在a.c文件对应的头文件a.h中对a.c文件的函数做显示的声明(extern “C”{ func1 func2 … })。
但上述处理同样会出现一个问题,就是a.c文件只能被.cpp文件调用,如果现在同时需要一个b.c文件调用a.c函数,那么extern “C” 会被gcc编译器视为非法语句。
解决办法用宏定义,如下代码:
g++ 在编译生成可执行程序时若需要链接库文件,需要添加 -L -l 选项指定库的位置,和库的名称。且库的名称是去掉前后缀lib和.so的文件名,位置默认在系统lib目录,不会在当前目录下寻找。
故通常需要为linux修改环境变量,为库文件的位置环境变量上添加当前目录,同时最好为二进制执行程序也添加当前目录。
可在终端中使用 ldd命令查看执行程序链接的so文件
so文件是动态共享代码,故编译的时候需要添加编译选项 -fPIC,表示该代码是固定入口地址,在系统内存只有一份,供不同应用调用,链接生成so文件时,添加编译选项 -shared。
so文件的编译,见上文makefile
Linux下C编程
makefile
udp程序移植到Linux
cc 混合编程so库文件的编写
混合编程头文件编写
so库的编写
Windows下udp编程
#include <winsock2.h> #include <string.h> #include <stdio.h> int socket_send(const char * ip) { // socket version DWORD version; // windows socket asynchronous data WSADATA wsaData; version = MAKEWORD(1,1); // init socket WSAStartup(version,&wsaData); // define socket object int af = AF_INET; // TCP/IP protocol int type = SOCK_DGRAM; // UDP protocol int protocol = 0; // default SOCKET st = socket(af,type,protocol); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); // set null addr.sin_family = AF_INET; // TCP/IP protocol address addr.sin_port = htons(8080); // set port,function htons():HOST TO NET SHORT addr.sin_addr.S_un.S_addr = inet_addr(ip/*"127.0.0.1"*/); // set ip // send message printf("enter a message and start communite,end up with char * \n"); int rc = 0; char buffer[1024] = {0}; while(1) { memset(buffer,0,sizeof(buffer)); gets(buffer); //strcpy(buffer,"hello socket"); if(buffer[0]=='*') break; rc = sendto(st,buffer,strlen(buffer),0,(struct sockaddr *)&addr,sizeof(addr)); //test:printf("rc:%d,buffer:%s,to:%s\n",rc,buffer,inet_ntoa(addr.sin_addr)); } // release resource closesocket(st); WSACleanup(); return rc; } int socket_receive() { // socket version DWORD version; // windows socket asynchronous data WSADATA wsaData; version = MAKEWORD(1,1); // init socket WSAStartup(version,&wsaData); // define socket object int af = AF_INET; // TCP/IP protocol int type = SOCK_DGRAM; // UDP protocol int protocol = 0; // default SOCKET st = socket(af,type,protocol); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); // set null addr.sin_family = AF_INET; // TCP/IP protocol address addr.sin_port = htons(8080); // set port,function htons():HOST TO NET SHORT addr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); // ANY ip could be address as a receiver // bind socket and addr if(-1==bind(st,(struct sockaddr *)&addr,sizeof(addr))){ printf("socket bind error!\n"); return 0; } // receive message int rc = 0; char buffer[1024] = {0}; struct sockaddr_in fromAddr; // sender addr information memset(&addr,0,sizeof(fromAddr)); int len = sizeof(fromAddr); while(1) { memset(buffer,0,sizeof(buffer)); rc = recvfrom(st,buffer,sizeof(buffer),0,(struct sockaddr *)&fromAddr,&len); if(rc > 0 ){ printf("%s:%s\n",inet_ntoa(fromAddr.sin_addr),buffer); } } // release resource closesocket(st); WSACleanup(); return rc; }
QT项目下,在profile中需要添加lib,用于链接
LIBS += -l ws2_32
Linux下C编程
makefile
### 常用makefile# makefile主要有变量、标号(默认执行第一个标号)、指令(指令必须以TAB开头)、依赖 # 变量,使用变量 $(变量名) CC = g++ SRCS = main.cpp\ myudp.cpp #相应变量间的替换字符 OBJS = $(SRCS:.cpp=.o) EXEC = myapp start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) .cpp.o: #本例中,在linux下使用该makefile编译,编译时定义宏OS_LINUX $(CC) -o $@ -c $< -D OS_LINUX clean: #删除编译中间文件 rm -rf $(OBJS)
### 编译库文件的makefile
CC = gcc SRCS = myfunc.c OBJS = $(SRCS:.c=.o) EXEC = libmyfunc.so start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) -shared .c.o: $(CC) -o $@ -c $< -fPIC clean: rm -rf $(OBJS)
### 链接库文件的应用的makefile
CC = g++ SRCS = main.cpp OBJS = $(SRCS:.cpp=.o) EXEC = myapp start:$(OBJS) $(CC) -o $(EXEC) $(OBJS) -L . -l myfunc .cpp.o: $(CC) -o $@ -c $< clean: rm -rf $(OBJS)
udp程序移植到Linux
// 利用宏使得当前源码可在linux与window下都能执行 #include <string.h> #include <stdio.h> #ifndef OS_LINUX //当前在window下 #include <winsock2.h> #define SOCKLEN_T int #else //当前在linux下 #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #define SOCKET int #define SOCKLEN_T socklen_t #endif int socket_send(const char * ip) { #ifndef OS_LINUX // socket version DWORD version; // windows socket asynchronous data WSADATA wsaData; version = MAKEWORD(1,1); // init socket WSAStartup(version,&wsaData); #endif // define socket object int af = AF_INET; // TCP/IP protocol int type = SOCK_DGRAM; // UDP protocol int protocol = 0; // default SOCKET st = socket(af,type,protocol); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); // set null addr.sin_family = AF_INET; // TCP/IP protocol address addr.sin_port = htons(8080); // set port,function htons():HOST TO NET SHORT addr.sin_addr.s_addr = inet_addr(ip/*"127.0.0.1"*/); // set ip // send message printf("enter a message and start communite,end up with char * \n"); int rc = 0; char buffer[1024] = {0}; while(1) { memset(buffer,0,sizeof(buffer)); fgets(buffer,1024,stdin); //strcpy(buffer,"hello socket"); if(buffer[0]=='*') break; rc = sendto(st,buffer,strlen(buffer),0,(struct sockaddr *)&addr,sizeof(addr)); //test:printf("rc:%d,buffer:%s,to:%s\n",rc,buffer,inet_ntoa(addr.sin_addr)); } #ifndef OS_LINUX //当前在window下 closesocket(st); WSACleanup(); #else //当前在linux下 close(st); #endif return rc; } int socket_receive() { #ifndef OS_LINUX // socket version DWORD version; // windows socket asynchronous data WSADATA wsaData; version = MAKEWORD(1,1); // init socket WSAStartup(version,&wsaData); #endif // define socket object int af = AF_INET; // TCP/IP protocol int type = SOCK_DGRAM; // UDP protocol int protocol = 0; // default SOCKET st = socket(af,type,protocol); struct sockaddr_in addr; memset(&addr,0,sizeof(addr)); // set null addr.sin_family = AF_INET; // TCP/IP protocol address addr.sin_port = htons(8080); // set port,function htons():HOST TO NET SHORT addr.sin_addr.s_addr = htonl(INADDR_ANY); // ANY ip could be address as a receiver // bind socket and addr if(-1==bind(st,(struct sockaddr *)&addr,sizeof(addr))){ printf("socket bind error!\n"); return 0; } // receive message int rc = 0; char buffer[1024] = {0}; struct sockaddr_in fromAddr; // sender addr information memset(&addr,0,sizeof(fromAddr)); SOCKLEN_T len = sizeof(fromAddr); while(1) { memset(buffer,0,sizeof(buffer)); rc = recvfrom(st,buffer,sizeof(buffer),0,(struct sockaddr *)&fromAddr,&len); if(rc > 0 ){ printf("%s:%s\n",inet_ntoa(fromAddr.sin_addr),buffer); } } #ifndef OS_LINUX //当前在window下 closesocket(st); WSACleanup(); #else //当前在linux下 close(st); #endif return rc; }
Linux和Windows在使用udp编程上的差异(移植关键)主要有:
SOCKET类型是windows定义,linux下为int类型
由于历史原因,windows对于udp的支持为外挂形式,需要手动启动资源、关闭资源,linux无须,可用宏解决该问题
关闭socket的函数不同,windows下为closesocket(SOCKET),linux下为close(int)
htons函数头文件不同,linux下可用man查看该函数头文件,包括查看socket相关头文件。
win下需要头文件
c\c++ 混合编程、so库文件的编写
混合编程头文件编写
原理(c++调用c代码):C++函数具有继承重载等面向对象特性,在预编译时,预编译器对函数名有处理,而C的函数在预编译时函数名不会做改变(通过编译器 -E选项可以看到结果)。所以.cpp文件调用a.c文件的函数会出现函数未定义的情况,此时可在a.c文件对应的头文件a.h中对a.c文件的函数做显示的声明(extern “C”{ func1 func2 … })。
但上述处理同样会出现一个问题,就是a.c文件只能被.cpp文件调用,如果现在同时需要一个b.c文件调用a.c函数,那么extern “C” 会被gcc编译器视为非法语句。
解决办法用宏定义,如下代码:
#ifndef LIBMYFUNC_H #define LIBMYFUNC_H /* 此处__cplusplus是g++在编译cpp文件时默认定义的宏 原因是:c++文件引用c文件的函数时,对于函数的编译方式不同(涉及重载等)所以需要指明是c的函数,extern “C”作用及此 而c文件引用该函数时,extern “c” 在c语句中不合法。 故要根据实际情况,利用__cplusplus宏区分 */ #ifdef __cplusplus extern "C" { #endif int max(int a,int b); #ifdef __cplusplus } #endif #endif
so库的编写
Linux中库文件总是以libxxxx.so的固定格式出现,故编译链接输出的文件名需要是该格式g++ 在编译生成可执行程序时若需要链接库文件,需要添加 -L -l 选项指定库的位置,和库的名称。且库的名称是去掉前后缀lib和.so的文件名,位置默认在系统lib目录,不会在当前目录下寻找。
故通常需要为linux修改环境变量,为库文件的位置环境变量上添加当前目录,同时最好为二进制执行程序也添加当前目录。
可在终端中使用 ldd命令查看执行程序链接的so文件
so文件是动态共享代码,故编译的时候需要添加编译选项 -fPIC,表示该代码是固定入口地址,在系统内存只有一份,供不同应用调用,链接生成so文件时,添加编译选项 -shared。
cd vi .profile # 添加以下两句,Linux中环境变量地址以冒号:分隔 export PATH=$PATH:. export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
so文件的编译,见上文makefile
相关文章推荐
- Socket 编程 windows到Linux代码移植遇到的问题
- Socket 编程 windows到Linux代码移植遇到的问题
- linux下lame编程:wav转MP3示例代码
- windows到Linux代码移植遇到的问题
- UNIX-LINUX编程实践教程->第二章->实例代码注解->more01
- 为AM335x移植Linux内核主线代码(35)使用platform中的GPIO
- 关于matlab与c#混合编程产生的移植问题
- [代码实例][Linux系统编程]遍历目录
- windows读取bmp格式图像代码移植linux;windows代码移植linux,数据类型不匹配我问题;
- mysql 从linux 代码移植到windows mysql_fetch_row 接收不到任何数据,mysql也不反回错误
- linux代码移植到windows
- linux代码移植到windows下“error missing struct tag”
- c++代码在windows,aix,linux上的移植
- Linux下SQLite数据库移植与编程
- 将Linux代码移植到Windows的简单方法
- C语言常用宏定义 __FILE__,__LINE__,FUNCTION__实现代码跟踪调试(linux下c语言编程)
- [代码实例][Linux系统编程]列出目录下的文件和子目录
- 【代码参考网上的】linux串口编程学习笔记
- Linux移植随笔:对tslib库的ts_test测试程序代码的一点分析【转】
- GTK 代码从Linux移植到Windows心得