1

VBA と組み合わせたネイティブ dll の最小限の動作例を作成できません

次の 3 つの問題があります。

  • エラー 453 を解決できません (dll エントリ ポイントが見つかりません)
  • バリアックをマーシャリングする方法がわかりません

VBA (エクセル)

Option Explicit

Public Declare Sub KERNEL32_SLEEP _
    Lib "kernel32" _
    Alias "Sleep" (ByVal dwMilliseconds As Long)

Public Declare Sub CALLADAPTER_SIMPLE _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "simple" ()

Public Declare Function CALLADAPTER_ADD _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "add" (ByVal A As Integer, ByVal B As Integer) As Integer

Public Declare Sub CALLADAPTER_PRINT _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "print" (ByVal FormatSpecifier As String)

Sub TEST_KERNEL32_SLEEP()
    Call KERNEL32_SLEEP(2000) 'works
End Sub

Sub TEST_CALLADAPTER_SIMPLE()
    Call CALLADAPTER_SIMPLE 'error 453 can't find dll entry point
End Sub

Sub TEST_CALLADAPTER_ADD()
    Dim A, B, C As Integer
    A = 30
    B = 12
    C = CALLADAPTER_ADD(A, B) 'error 453 can't find dll entry point
    MsgBox "A + B = " & C
End Sub

Sub TEST_CALLADAPTER_PRINT()
    Call CALLADAPTER_PRINT("Hello World") 'error 453 can't find dll entry point
End Sub

Sub TEST_CALLADAPTER_PRINTF()
    'I do not know how to marshall variadic
End Sub

Ansi C (Visual Studio 2010)

// Header
#ifdef CALLADAPTER_EXPORTS
#define CALLADAPTER_API __declspec(dllexport)
#else
#define CALLADAPTER_API __declspec(dllimport)
#endif

CALLADAPTER_API void _stdcall simple( void );
CALLADAPTER_API int _stdcall add( int a, int b );
CALLADAPTER_API void _stdcall print( const char * msg );
CALLADAPTER_API int _stdcall printf( const char * format, ... );   



// code
#include "CallAdapter.h"
#include <stdio.h>
#include <stdarg.h>

CALLADAPTER_API void _stdcall simple( void )
{
    printf("simple was called\n");
}

CALLADAPTER_API int _stdcall add( int a, int b )
{
    return a + b;
}

CALLADAPTER_API void _stdcall print( const char * msg )
{
    printf( "%s", msg );
}

CALLADAPTER_API int _stdcall printf( const char * format, ... )
{
    int ret;
    va_list args;
    va_start( args, format );
    ret = vprintf( format, args );
    va_end( args );
    return ret;
}

編集#1:問題をよりよく説明するために、例を完全に作り直しました。


編集 #2: variadic で進行します。

ウェブ上に非常に便利なサイトがあります。

私はいくつかの進歩を遂げましたが、まだ呼び出しを完了できません...

VBA

Option Explicit

Public Declare Function CallAdapter_sprintf _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "sprintf" (ByRef DST As String, ByRef FORMAT As String, ParamArray args()) As Integer

Sub TEST_CALLADAPTER_sprintf()
    Dim DESTINATION, FORMAT As String
    Dim OTHER() As Variant
    Dim C As Integer

    FORMAT = "%s"
    OTHER = Array("Hello World")
    DESTINATION = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"

    C = CallAdapter_sprintf(DESTINATION, FORMAT, OTHER)
    MsgBox "RET " & C & " -> " & DESTINATION
End Sub

アンシ C

CALLADAPTER_API int _stdcall sprintf( char * dest, const char * format, ... )
{
    int ret;
    va_list args;
    va_start( args, format );
    ret = vsprintf( dest, format, args );
    va_end( args );
    return ret;
}
4

1 に答える 1

1

バロカルバスは良いヒントを与えてくれました。

Dependency Walkerを使用して正しい名前を取得しました。これは私の問題の半分を解決しますが、可変個引数をマーシャリングする方法はまだわかりません

Public Declare Sub CALLADAPTER_SIMPLE _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "_simple@0" ()

Public Declare Function CALLADAPTER_ADD _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "_add@8" (ByVal A As Integer, ByVal B As Integer) As Integer

Public Declare Sub CALLADAPTER_PRINT _
    Lib "D:\Stackoverflow\Release\CallAdapter.dll" _
    Alias "_print@4" (ByVal FormatSpecifier As String)

stdout が存在しないように見えるため、ADD の例のみが良い例です。

于 2013-08-15T15:23:57.047 に答える