Windows的ipref3 dll

时间:2018-08-08 05:15:42

标签: windows dll cygwin

我尝试为Windows构建ipref3.dll

我发现了How to compile iperf3 for Windows

将其构建,但我只有iperf3.exe和libiperf.a

我发现了如何创建dll手册

gcc -s -shared -o iperf3.dll units.o timer.o tcp_window_size.o tcp_info.o net.o iperf_util.o iperf_sctp.o iperf_udp.o iperf_tcp.o iperf_server_api.o iperf_locale.o iperf_client_api.o iperf_error.o iperf_api.o cjson.o -Wl,--enable-auto-import,--export-all-symbols,--subsystem,windows

我发现需要初始化之后

HMODULE h = LoadLibrary(TEXT("cygwin1.dll"));
PFN_CYGWIN_DLL_INIT init = (PFN_CYGWIN_DLL_INIT)GetProcAddress(h, "cygwin_dll_init");
init();

现在我可以加载dll并进行初始化,但是当我开始测试时,iperf_run_client应用程序已崩溃

  

iprerf-server.exe中0x611537C0(cygwin1.dll)的未处理异常:   0xC0000005:访问冲突读取位置0x00740000。

如何解决这个问题?

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <WinSock2.h>
//#include <unistd.h>
#include <string.h>
//#include <sysexits.h>
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif

#include "iperf_api.h"

#ifdef WIN64
#pragma comment(lib, "iperf3_64.lib")
#else
#pragma comment(lib, "iperf3.lib")
#endif

#pragma comment(lib, "ws2_32.lib")


typedef void *register_frame();
typedef int *hello_f();

typedef int(*PFN_HELLO)();
typedef void(*PFN_CYGWIN_DLL_INIT)();

#pragma pack(push, 1) 

int main(int argc, char** argv)
{
    WSADATA wsaData;
    int wsaErr = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (wsaErr != 0) {
        printf("WSAStartup failed with error: %d\n", wsaErr);
        return 1;
    }

    //PFN_HELLO fnHello;
    HMODULE /*hLib, */h = LoadLibrary(TEXT("cygwin1.dll"));
    PFN_CYGWIN_DLL_INIT init = (PFN_CYGWIN_DLL_INIT)GetProcAddress(h, "cygwin_dll_init");
    init();

    char* argv0;
    char* host;
    int port;
    struct iperf_test *test;

    argv0 = strrchr(argv[0], '/');
    if (argv0 != (char*)0)
        ++argv0;
    else
        argv0 = argv[0];

    if (argc != 3) {
        fprintf(stderr, "usage: %s [host] [port]\n", argv0);
        exit(EXIT_FAILURE);
    }
    host = argv[1];
    port = atoi(argv[2]);

    test = iperf_new_test();
    if (test == NULL) {
        fprintf(stderr, "%s: failed to create test\n", argv0);
        exit(EXIT_FAILURE);
    }
    iperf_defaults(test);
    iperf_set_verbose(test, 1);

    iperf_set_test_role(test, 'c');
    iperf_set_test_server_hostname(test, host);
    iperf_set_test_server_port(test, port);
    /* iperf_set_test_reverse( test, 1 ); */
    iperf_set_test_omit(test, 3);
    iperf_set_test_duration(test, 5);
    iperf_set_test_reporter_interval(test, 1);
    iperf_set_test_stats_interval(test, 1);
    /* iperf_set_test_json_output( test, 1 ); */

    if (iperf_run_client(test) < 0) {
        fprintf(stderr, "%s: error - %s\n", argv0, iperf_strerror(i_errno));
        exit(EXIT_FAILURE);
    }

    if (iperf_get_test_json_output_string(test)) {
        fprintf(iperf_get_test_outfile(test), "%zd bytes of JSON emitted\n",
            strlen(iperf_get_test_json_output_string(test)));
    }

    iperf_free_test(test);
    exit(EXIT_SUCCESS);

}

2 个答案:

答案 0 :(得分:0)

未构建共享库的原因是:

libtool: warning: undefined symbols not allowed in x86_64-unknown-cygwin 
shared libraries; building static only

在干净的版本中,绕过它的简单方法是使用:

$ make libiperf_la_LIBADD="-no-undefined"

该版本将包括共享的libray和导入库

$ find . -name "*dll*"
./src/.libs/cygiperf-0.dll
./src/.libs/libiperf.dll.a

对于我所见,在cygwin上进行构建也需要删除定义 在运行src/iperf_config.h

之后在configure中运行
/* #define HAVE_SETPROCESSAFFINITYMASK 1 */

PS#1:iperf-2.0.5-1作为cygwin软件包提供
PS#2:您的代码类似于Windows,而Cygwin是类似于Unix的系统,您不能将它们混合使用

答案 1 :(得分:0)

我找到了解决办法

1)它需要创建附加dll:my_crt0.dll

#include <sys/cygwin.h>
#include <stdlib.h>

typedef int (*MainFunc) (int argc, char *argv[], char **env);

void my_crt0 (MainFunc f)
{
    cygwin_crt0(f);
}
gcc -c my_crt0.c
gcc -o my_crt0.dll my_crt0.o -s -shared -Wl,--subsystem,windows,--enable-auto-import,--export-all-symbols,--out-implib,my_crt0.lib

2)修改主代码

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <WinSock2.h>
#include <string.h>

#include "iperf_api.h"

#pragma comment(lib, "iperf3.lib")
#pragma comment(lib, "ws2_32.lib")

typedef int(*MainFunc) (int argc, char *argv[], char **env);
typedef void(*my_crt0)(MainFunc f);

int main2(int argc, char** argv, char **env)
{
    char* argv0;
    char* host;
    int port;
    struct iperf_test *test;

    host = (char*)"127.0.0.1";
    port = 4000; 

    test = iperf_new_test();
    if (test == NULL) {
        exit(EXIT_FAILURE);
    }

    iperf_defaults(test);
    iperf_set_verbose(test, 1);

    iperf_set_test_role(test, 'c');
    iperf_set_test_server_hostname(test, host);
    iperf_set_test_server_port(test, port);
    /* iperf_set_test_reverse( test, 1 ); */
    iperf_set_test_omit(test, 3);
    iperf_set_test_duration(test, 5);
    iperf_set_test_reporter_interval(test, 1);
    iperf_set_test_stats_interval(test, 1);
    /* iperf_set_test_json_output( test, 1 ); */

    iperf_strerror(0);

    if (iperf_run_client(test) < 0) {
        fprintf(stderr, "%s: error - %s\n", argv0, iperf_strerror(i_errno));
        exit(EXIT_FAILURE);
    }

    if (iperf_get_test_json_output_string(test)) {
        fprintf(iperf_get_test_outfile(test), "%zd bytes of JSON emitted\n",
            strlen(iperf_get_test_json_output_string(test)));
    }

    iperf_free_test(test);
    exit(EXIT_SUCCESS);

    return 1;
}

int main(int argc, char** argv)
{
    WSADATA wsaData;
    int wsaErr = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (wsaErr != 0) {
        printf("WSAStartup failed with error: %d\n", wsaErr);
        return 1;
    }

    {
        HMODULE /*hLib, */h = LoadLibrary(TEXT("my_crt0.dll"));
        my_crt0 init = (my_crt0)GetProcAddress(h, "my_crt0");
        init(main2);
    }

    exit(EXIT_SUCCESS);
}

现在它已编译并可以在VS 2015中使用