2

我尝试为 Windows 构建 ipref3.dll

我找到了如何为 Windows 编译 iperf3

构建它,但我只有 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 应用程序崩溃了

iperf-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);

}
4

2 回答 2

1

未构建共享库的原因是:

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

在干净的构建中绕过它的简单方法是使用:

$ make libiperf_la_LIBADD="-no-undefined"

构建将包括共享库和导入库

$ 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 的系统,您不能混合使用它们

于 2018-08-08T08:09:34.383 回答
1

我找到了解决方案

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

于 2018-08-13T05:47:26.150 回答