-7

ビルドしようとしている C ファイルがありますが、リンカー エラーが発生します。これは、他のソース ファイルで定義されているメソッド定義が見つからないためです。
ここでまさに私がやろうとしているのは、このソース ファイルによって特定されるメソッドの定義を作成することです。私が構築しようとしているメインプログラムであるコードを提供しています。どんな提案でも大歓迎です。

#include<stdio.h>
#include<jni.h>
#include<windows.h>
#include <stdbool.h>
#include "RunnerClass.h"
#include "unistd.h"
#include "apr_getopt.h"
#include "apr_portable.h"
#include "C:\JNItest\src\common\error_debug.h"
#include "C:\JNItest\src\common\event.h"
#include "C:\JNItest\src\common\context.h"
#include "C:\JNItest\src\common\alloc.h"
#include "C:\JNItest\src\core\nxlog.h"
#include "C:\JNItest\src\core\modules.h"
#include "C:\JNItest\src\core\router.h"
#include "C:\JNItest\src\core\ctx.h"
#include "C:\JNItest\src\core\core.h"
#define NX_LOGMODULE NX_LOGMODULE_CORE


static nxlog_t nxlog;
static apr_os_thread_t _nxlog_initializer = 0;
static void WINAPI nx_win32_svc_main(DWORD argc, LPTSTR * argv);
static void WINAPI nx_win32_svc_change(DWORD);
extern void nx_logger_disable_foreground();
static void print_usage();
static void set_configfile();

static bool do_install = FALSE;
static bool do_uninstall = FALSE;
static SERVICE_STATUS svc_status;
static SERVICE_STATUS_HANDLE *svc_status_handle = NULL;

JNIEXPORT void JNICALL Java_RunnerClass_parse_1cmd_1line
  (JNIEnv * env, jobject jobj, jint argc, const jstring * const *argv){
        char *opt_arg;
        int rv;
        apr_getopt_t *opt;
        int ch;

        static apr_getopt_option_t options[] = {
        { "help", 'h', 0, "print help" }, 
        { "foreground", 'f', 0, "run in foreground" },
        { "stop", 's', 0, "stop a running instance" },
//      { "reload", 'r', 0, "reload configuration of a running instance" },
        { "conf", 'c', 1, "configuration file" }, 
        { "verify", 'v', 0, "verify configuration file syntax" },
        { "install", 'i', 0, "install service available to service manager" },
        { "uninstall", 'u', 0, "uninstall service" },
        { NULL, 0, 1, NULL }, 
        };

        apr_getopt_init(&opt, nxlog.pool, argc,(void *) argv);
        while ( (rv = apr_getopt_long(opt, options, &ch,(void *) &opt_arg)) == APR_SUCCESS )
        {
        switch ( ch )
        {
            case 'c':   /* configuration file */
            nxlog.cfgfile = apr_pstrdup(nxlog.pool, opt_arg);
            break;
            case 'f':   /* foreground */
            nxlog.foreground = TRUE;
            break;
            case 'h':   /* help */
            print_usage();
            exit(-1);
            case 's':   /* stop */
            nxlog.do_stop = TRUE;
            break;
    /*
            case 'r':   // reload
            nxlog.do_restart = true;
            break;
    */
            case 'v':   /* verify */
            nxlog.verify_conf = TRUE;
            nxlog.ctx->ignoreerrors = FALSE;
            break;
            case 'i':   /* install */
            do_install = TRUE;
            break;
            case 'u':   /* uninstall */
            do_uninstall = TRUE;
            break;
            default:
            print_usage();
            exit(-1);
        }
        }

        set_configfile();
        if ( (rv != APR_SUCCESS) && (rv !=APR_EOF) )
        {
            throw(rv ,"Could not parse options");///////////
        }       
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1stop
  (JNIEnv * env, jobject jobj){
        SC_HANDLE service_manager = NULL;
        SC_HANDLE service_handle = NULL;
        SERVICE_STATUS status;
        nx_exception_t e;

        // Connect to service manager
        service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if ( service_manager == NULL )
        {
        nx_win32_error("Cannot initialize access to the service manager");
        }
        try
        {
        service_handle = OpenService(service_manager, "nxlog", SERVICE_ALL_ACCESS);
        if ( service_handle == NULL )
        {
            nx_win32_error("Couldn't open nxlog service");
        }
        else
        {
            if ( QueryServiceStatus(service_handle, &status) )
            {
            if ( status.dwCurrentState != SERVICE_STOPPED )
            {
                log_info("Service currenty active - stopping service...");
                if ( !ControlService(service_handle, SERVICE_CONTROL_STOP, &status) )
                {
                nx_win32_error("Couldn't stop service");
                }
                else
                {
                Sleep(500);
                }
            }
            else
            {
                log_error("Service is already stopped");
            }
            }
            // Close connection to service
            CloseServiceHandle(service_handle);
        }
        // Close connection to service manager
        CloseServiceHandle(service_manager);
        }
        catch(e)
        {
        if ( service_handle != NULL )
        {
            CloseServiceHandle(service_handle);

        }
        if ( service_manager != NULL )
        {
            CloseServiceHandle(service_manager);

        }
        rethrow(e);
        }
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1install
  (JNIEnv * env, jobject jobj){
    SC_HANDLE service_manager;
    SC_HANDLE new_service = NULL;
    HKEY regkey;
    uint32_t regtype = 0;
    char regvalbuf[1024];
    uint32_t regvalbufsize = 1024;
    char servicename[1024];

    // Connect to service manager
    service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if ( service_manager == NULL )
    {
    nx_win32_error("Cannot initialize access to the service manager");
    }

    //FIXME use nxlog.ctx.user to invoke service in CreateService

    // default in case registry lookup would fail
    apr_cpystrn(servicename, 
        "\"c:\\Program Files\\nxlog\\nxlog.exe\" -c \"c:\\Program Files\\nxlog\\nxlog.conf\"",
        sizeof(servicename));

    if ( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\nxlog", &regkey) == ERROR_SUCCESS )
    {
    if ( RegQueryValueEx(regkey, "installdir", 0,(void *) &regtype,(unsigned char *) regvalbuf,(void *) &regvalbufsize) == ERROR_SUCCESS )
    {
        if ( regtype == REG_SZ )
        {
        apr_snprintf(servicename, sizeof(servicename), "\"%snxlog.exe\"", regvalbuf);
        }
    }
    RegCloseKey(regkey);
    }

    // Install the new service
    new_service = CreateService(service_manager, "nxlog", "nxlog",
                SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
                SERVICE_AUTO_START, SERVICE_ERROR_IGNORE,
                servicename, NULL, NULL,
                "eventlog\0", NULL, NULL);
    if ( new_service == NULL )
    {
    nx_win32_error("Couldn't create service");
    }
    else
    {
    CloseServiceHandle(new_service);
    log_info("Service successfully installed");
    }

    // Close the connection to service manager
    CloseServiceHandle(service_manager);        
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1uninstall
  (JNIEnv * env, jobject jobj){
          SC_HANDLE service_manager = NULL;
        SC_HANDLE service_handle = NULL;
        SERVICE_STATUS query_status;
        nx_exception_t e;

        // Connect to service manager
        service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
        if ( service_manager == NULL )
        {
        nx_win32_error("Cannot initialize access to the service manager");
        }

        try
        {
        // Connect to service
        service_handle = OpenService(service_manager, "nxlog", SERVICE_ALL_ACCESS | DELETE);
        if ( service_handle == NULL )
        {
            nx_win32_error("Couldn't open nxlog service");
        }
        else
        {
            // Check that the service is stopped
            if ( QueryServiceStatus(service_handle, &query_status) &&
             (query_status.dwCurrentState == SERVICE_RUNNING) )
            {
            throw_msg("Service is running, please stop it first.");
            }
            else
            { // we can remove
            if ( DeleteService(service_handle) == FALSE )
            {
                nx_win32_error("Couldn't delete service");
            }
            else
            {
                log_info("Service successfully uninstalled");
            }
            }
            // Close connection to service
            CloseServiceHandle(service_handle);
        }
        // Close connection to service manager
        CloseServiceHandle(service_manager);
        }
        catch(e)
        {
        if ( service_handle != NULL )
        {
            CloseServiceHandle(service_handle);

        }
        if ( service_manager != NULL )
        {
            CloseServiceHandle(service_manager);

        }
        rethrow(e);
        }
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1main
  (JNIEnv * env, jobject jobj, jint argc, jstring *argv){
          nx_context_t thread_context;
          nx_exception_t e;

    if ( _nxlog_initializer == 0 )
    { // running from service manager
    ASSERT(nx_init((void *)&argc, (void *)&argv, NULL) == TRUE);

    nxlog_init(&nxlog);
    nx_logger_disable_foreground();
    }
    else if ( _nxlog_initializer != apr_os_thread_current() )
    {
    // service dispatcher runs in a new thread, we need
    // to initialize the exception context.
    _nxlog_initializer = apr_os_thread_current();
    memset(&thread_context, 0, sizeof(nx_context_t));
    init_exception_context(&thread_context.exception_context);
    apr_threadkey_private_set(&thread_context, nx_get_context_key());
    }

    log_debug("nx_win32_svc_main");

    try
    {
    // read config cache
    nx_config_cache_read();
    log_debug("nxlog cache read");

    // load DSO and read and verify module config
    nx_ctx_config_modules(nxlog.ctx);
    log_debug("nxlog config OK");

    // initialize modules
    nx_ctx_init_modules(nxlog.ctx);

    // initialize log routes
    nx_ctx_init_routes(nxlog.ctx);
    nx_ctx_init_jobs(nxlog.ctx);

    nx_ctx_restore_queues(nxlog.ctx);

    // setup threadpool
    nxlog_create_threads(&nxlog);

    // start modules
    nx_ctx_start_modules(nxlog.ctx);

    if ( nxlog.foreground != TRUE )
    {
        // register to service manager
        svc_status_handle = (void *)RegisterServiceCtrlHandler("nxlog", nx_win32_svc_change);
        if ( svc_status_handle == 0 )
        {
        nx_win32_error("RegisterServiceCtrlHandler() failed, couldn't register the service control handler");
        }

        // Signal to svc manager that we are running
        svc_status.dwWin32ExitCode = 0;
        svc_status.dwServiceSpecificExitCode = 0;
        svc_status.dwCheckPoint = 0;
        svc_status.dwWaitHint = 0; 
        svc_status.dwServiceType = SERVICE_WIN32;
        svc_status.dwCurrentState = SERVICE_RUNNING;
        svc_status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
        if ( SetServiceStatus(*svc_status_handle, &svc_status) == FALSE )
        {
        nx_win32_error("Cannot send start service status update");
        }
    }

    //log_info(PACKAGE"-"VERSION_STRING" started");
    }
    catch(e)
    {
    log_exception(e);
    log_error("exiting...");
    svc_status.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(*svc_status_handle, &svc_status);
    exit(e.code);
    }

    // mainloop
    nxlog_mainloop(&nxlog, FALSE);

    nxlog_shutdown(&nxlog);

    if ( nxlog.foreground != TRUE )
    {
    // Signal back that we are stopped
    svc_status.dwCurrentState = SERVICE_STOPPED;
    SetServiceStatus(*svc_status_handle, &svc_status);
    }

    nxlog_exit_function();
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1dispatch
  (JNIEnv * env, jobject jobj){
         static SERVICE_TABLE_ENTRY svc_dispatch_table[] = 
    {
    { "nxlog", NULL },
    { NULL, NULL }
    };

    if ( StartServiceCtrlDispatcher(svc_dispatch_table) == FALSE )
    {
    nx_win32_error("Cannot start service dispatcher");
    } 
  }

  JNIEXPORT void JNICALL Java_RunnerClass_nx_1win32_1svc_1start
  (JNIEnv * env, jobject jobj, jint argc, jstring argv){
          SC_HANDLE service_manager = NULL;
    SC_HANDLE service_handle = NULL;
    SERVICE_STATUS status;
    nx_exception_t e;

    // Connect to service manager
    service_manager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if ( service_manager == NULL )
    {
    nx_win32_error("Cannot initialize access to the service manager");
    }
    try
    {
    service_handle = OpenService(service_manager, "nxlog", SERVICE_ALL_ACCESS);
    if ( service_handle == NULL )
    {
        nx_win32_error("Couldn't open nxlog service");
    }
    else
    {
        if ( QueryServiceStatus(service_handle, &status) )
        {
        if ( status.dwCurrentState != SERVICE_RUNNING )
        {
            log_info("Service not running - starting service...");
            if ( StartService(service_handle, argc,(void *) argv) == 0 )
            {
            nx_win32_error("Failed to start nxlog service");
            }
        }
        else
        {
            log_error("Service is already running");
        }
        }

        // Close connection to service
        CloseServiceHandle(service_handle);
    }
    // Close connection to service manager
    CloseServiceHandle(service_manager);
    }
    catch(e)
    {
    if ( service_handle != NULL )
    {
        CloseServiceHandle(service_handle);

    }
    if ( service_manager != NULL )
    {
        CloseServiceHandle(service_manager);

    }
    rethrow(e);
    }
  }

JNIEXPORT void JNICALL Java_RunnerClass_nxlog_1exit_1function
  (JNIEnv * env, jobject jbobj){
  static bool exited = FALSE;

    if ( exited == TRUE )
    {
    return;
    }
    exited = TRUE;

    if ( _nxlog_initializer == 0 )
    {
    return;
    }

    if ( nxlog.pid != (int) getpid() )
    {
    return;
    }

    nx_ctx_free(nxlog.ctx);
    apr_pool_destroy(nxlog.pool);
    apr_terminate();      
  }

  /* Callback for service changes */
static void WINAPI nx_win32_svc_change(DWORD cmd)
{
    // Only STOP command is handled
    switch ( cmd )
    {
    case SERVICE_CONTROL_STOP:
        log_warn("stopping nxlog service");
        nxlog.terminate_request = TRUE;
        // Wait until service stops
        while ( svc_status.dwCurrentState != SERVICE_STOPPED )
        {
        Sleep(500);
        }
        break;
    case SERVICE_CONTROL_INTERROGATE:
        // ignore
        log_debug("ignoring unsupported service change request: SERVICE_CONTROL_INTERROGATE");
        break;
    case SERVICE_CONTROL_PAUSE:
        log_warn("ignoring unsupported service change request: SERVICE_CONTROL_PAUSE");
        break;
    case SERVICE_CONTROL_CONTINUE:
        log_warn("ignoring unsupported service change request: SERVICE_CONTROL_CONTINUE");
        break;
    case SERVICE_CONTROL_PARAMCHANGE:
        log_warn("ignoring unsupported service change request: SERVICE_CONTROL_PARAMCHANGE");
        break;
    case 200:
        nxlog_dump_info();
            break;
    case 201:
    {
        nx_ctx_t *ctx;

        log_info("got user control signal, switching to debug loglevel");
        ctx = nx_ctx_get();
        ctx->loglevel = NX_LOGLEVEL_DEBUG;
    }
    break;
    default:
        log_warn("ignoring unsupported service change request (%d)", cmd);
    }
}

static void print_usage()
{
    printf(/*PACKAGE*/ "-" /*ERSION_STRING*/ "\n"
       " usage: "
       " nxlog.exe [OPTIONS]\n"
       "   [-h] print help\n"
       "   [-f] run in foreground, otherwise try to start the nxlog service\n"
       "   [-c conffile] specify an alternate config file\n"
       "   [-i] install service available to service manager\n"
       "   [-u] uninstall service\n"
       "   [-s] stop running nxlog service\n"
       "   [-v] verify configuration file syntax\n"
       );
//     "   [-r] reload configuration of a running instance\n"
}

static void set_configfile()
{
    HKEY regkey;
    uint32_t regtype = 0;
    char regvalbuf[1024];
    uint32_t regvalbufsize = 1024;

    if ( nxlog.cfgfile != NULL )
    {
    return;
    }

    if ( RegOpenKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\nxlog", &regkey) == ERROR_SUCCESS )
    {
    if ( RegQueryValueEx(regkey, "installdir", 0, (void *)&regtype,
                 (unsigned char *) regvalbuf,(void *) &regvalbufsize) == ERROR_SUCCESS )
    {
        if ( regtype == REG_SZ )
        {
        nxlog.cfgfile = apr_psprintf(nxlog.pool, "%sconf\\nxlog.conf", regvalbuf);
        }
    }
    RegCloseKey(regkey);
    }

    if ( nxlog.cfgfile == NULL )
    {
    //nxlog.cfgfile = apr_pstrdup(nxlog.pool, NX_CONFIGFILE);
    }
}
4

2 に答える 2

0

「メソッド」が宣言されている可能性がありますが、定義されていません。

すなわち

void method(void);

どこかにあります(できればヘッダーファイル)が、

void method(void)
{
    //do stuff
}

見つかりません。「メソッド」が定義されていることを確認します。

于 2013-02-12T13:58:23.717 に答える
0

あなたが得ている正確なエラーメッセージは何ですか???

メモリから、JNIEXPORT には ' extern "C" ' が含まれていません。そのため、ソース ファイルが C++ の場合、関数名はマングルされます (リンカはそれらを見つけられません)。

于 2013-02-12T14:37:56.600 に答える