Linux下代码移植及混合编程


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编程上的差异(移植关键)主要有:

  1. SOCKET类型是windows定义,linux下为int类型
  2. 由于历史原因,windows对于udp的支持为外挂形式,需要手动启动资源、关闭资源,linux无须,可用宏解决该问题
  3. 关闭socket的函数不同,windows下为closesocket(SOCKET),linux下为close(int)
  4. htons函数头文件不同,linux下可用man查看该函数头文件,包括查看socket相关头文件。
  5. 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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值