-1

一部の Tcl メソッドのロード可能な DLL を作成したいと考えています。しかし、これを行う方法がわかりません。そのために、2 つの数値を加算して合計を出力する tcl api の簡単な例を取り上げました。ここで、この tcl 機能をエクスポートするためのロード可能な DLL を作成したいと考えています。

しかし、Visual Studio でそれを行う方法がわかりません。この tcl api を呼び出して 2 つの整数の合計を取得できる C コードを作成しましたが、この方法で実行したくありません。この tcl 機能を使用する DLL ファイルを作成したいと考えています。Visual Studio 2010 でこの DLL を作成するにはどうすればよいですか。

以下は、私が使用しているサンプル tcl プログラムです。

#!/usr/bin/env tclsh8.5
proc add_two_nos { } {

set a 10

set b 20

set c [expr { $a + $b } ]

puts " c is $c ......."

}

この tcl 機能を使用できる C コードは次のとおりです。

#include <tcl.h>
#include <stdio.h>
#include <stdlib.h>

    int main(int argc, char **argv) {
    Tcl_Interp *interp;
    int code;
    char *result;

    Tcl_FindExecutable(argv[0]);
    interp = Tcl_CreateInterp();
    code = Tcl_Eval(interp, "source myscript.tcl; add_two_nos");

    /* Retrieve the result... */
    result = Tcl_GetString(Tcl_GetObjResult(interp));

    /* Check for error! If an error, message is result. */
    if (code == TCL_ERROR) {
    fprintf(stderr, "ERROR in script: %s\n", result);
    exit(1);
    }

    /* Print (normal) result if non-empty; we'll skip handling encodings for now */
    if (strlen(result)) {
    printf("%s\n", result);
    }

    /* Clean up */
    Tcl_DeleteInterp(interp);
    exit(0);
    }

以下のコマンドでこのコードを正常にコンパイルしました gcc simple_addition_wrapper_new.c -I/usr/include/tcl8.5/ -ltcl8.5 -o simple_addition_op

上記のコードは、期待される出力で動作しています。

Visual Studio 2010 でこのためのロード可能な dll を作成するには、どのような手順を実行する必要がありますか?

4

1 に答える 1

0

この質問への回答を見ると、ここでは、実行する必要があるプロセスの基本的な概要が示されています。私の回答から、DLL の作成に関する Microsoft MSDN の記事へのリンクがあります。

Tcl が組み込まれている C++ dll について、もう少し詳しく説明します。

最初のステップは、シンボルをエクスポートする dll をビルドする、正しいタイプの新しい Visual Studio プロジェクトを作成することです。サンプル プロジェクトは TclEmbeddedInDll と呼ばれ、その名前は Visual Studio によって生成される TCLEMBEDDEDINDLL_API などのシンボルのコードに表示されます。

dllmain.cpp は次のようになります。

// dllmain.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
    )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        {
            allocInterp() ;
            break ;
        }

    case DLL_THREAD_ATTACH:
        break ;
    case DLL_THREAD_DETACH:
        break ;
    case DLL_PROCESS_DETACH:
        {
            destroyInterp() ;
            break;
        }
    }
    return TRUE;
}

および関数は TclEmbeddedInDll.h で定義されallocInterp()destroyInterp()います。Tcl_Interp を直接作成するのではなく、ここで関数を使用する理由は、Tcl に関する詳細を DLL インターフェイスから遠ざけるためです。ここで interp を作成すると、tcl.h をインクルードする必要があり、別のプログラムで DLL を使用しようとすると事態が複雑になります。

TclEmbeddedInDll.h と .cpp が次に表示されます。関数fnTclEmbeddedInDll()は DLL からエクスポートされたものです。他の言語 IMHO から関数を呼び出すのが簡単になるため、C++ ではなく C リンケージを使用しています。

// The following ifdef block is the standard way of creating macros which make exporting 
// from a DLL simpler. All files within this DLL are compiled with the TCLEMBEDDEDINDLL_EXPORTS
// symbol defined on the command line. This symbol should not be defined on any project
// that uses this DLL. This way any other project whose source files include this file see 
// TCLEMBEDDEDINDLL_API functions as being imported from a DLL, whereas this DLL sees symbols
// defined with this macro as being exported.
#ifdef TCLEMBEDDEDINDLL_EXPORTS
#define TCLEMBEDDEDINDLL_API __declspec(dllexport)
#else
#define TCLEMBEDDEDINDLL_API __declspec(dllimport)
#endif

extern "C" {
    TCLEMBEDDEDINDLL_API void fnTclEmbeddedInDll(void);

}

void allocInterp() ;
void destroyInterp() ;


// TclEmbeddedInDll.cpp : Defines the exported functions for the DLL application.
//

#include "stdafx.h"

extern "C" {

    static Tcl_Interp *interp ;

    // This is an example of an exported function.
    TCLEMBEDDEDINDLL_API void fnTclEmbeddedInDll(void)
    {
        int code;
        const char *result;
        code = Tcl_Eval(interp, "source simple_addition.tcl; add_two_nos");
        result = Tcl_GetString(Tcl_GetObjResult(interp));
    }
}

void allocInterp() 
{
    Tcl_FindExecutable(NULL);
    interp = Tcl_CreateInterp();
}

void destroyInterp()
{
    Tcl_DeleteInterp(interp);
}

allocInterp() と destroyInterp() の実装は非常に素朴で、エラー チェックは行われません。

最後に、DLL の場合、stdafx.h ファイルは次のようにすべてを結び付けます。

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//

#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
// Windows Header Files:
#include <windows.h>

// TODO: reference additional headers your program requires here
#include <tcl.h>
#include "TclEmbeddedInDll.h"
于 2013-01-30T09:15:10.273 に答える