C# プロジェクトで動作させようとしている C++ dll があります (C++/C については何も知りませんが、ソースがあり、VS2013 で開いてビルドできます)。
dll には Excel VBA で動作する例が付属していましたが、C# で動作させることはできません。
私が直面し続けるエラーは...
追加情報: PInvoke 関数 'RMTest!RMTest.PInvokeTest::encode_eib_d' の呼び出しにより、スタックのバランスが崩れました。これは、管理された PInvoke 署名が管理されていない署名と一致しないことが原因である可能性があります。
私のC#テストコードは次のとおりです...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
namespace RMTest
{
class Program
{
static void Main(string[] args)
{
string s1 = "2";
string s2 = "1";
string s3 = "1";
string s4 = "1";
string s5 = "TESTTE";
var res = PInvokeTest.encode_eib_d(s1, s2, s3, s4, s5);
}
}
class PInvokeTest
{
[DllImport("UKRM_EncodeEIB_D.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern string encode_eib_d(string infoID, string versionID, string format, string sClass, string licNum);
}
}
参考までに、Excelでの作業例、VBAは次のとおりです...
Public Declare _
Function encode_eib_d Lib "UKRM_EncodeEIB_D.dll" (ByVal inInfoID As String, ByVal inVersionID As String, ByVal inClass As String, _
ByVal inFormat As String, ByVal inLicenseNum As String) As Variant
Function ENCODE_D(inInfoID As String, inVersionID As String, inFormat As String, inClass As String, inLicenseNum As String) As Variant
Dim error As Integer
ChDrive (ActivePath())
ChDir (ActivePath())
On Error GoTo ErrHandler:
ENCODE_D = encode_eib_d(inInfoID, inVersionID, inFormat, inClass, inLicenseNum)
ErrHandler:
If Err.Number <> 0 Then
ENCODE_D = Err.Description
End If
End Function
C++ dll の関連するコードのスニペット (私が知る限り) は次のとおりです...
ヘッダー (.h):
#include "UKRM_EncodeEIB_D.h"
#include <WTypes.h>
#include <tchar.h>
#include <comutil.h>
#include <malloc.h>
#include <atlconv.h>
extern "C" {
VARIANT __stdcall CallEncode(LPCSTR sInfoID, LPCSTR sVersionId, LPCSTR sFormat, LPCSTR sClass, LPCSTR sLicenseNum);
}
.cpp
#include "UKRM_EncodeEIB_D_DLL.h"
// ******************************************************************************
// * CallEncode
// ******************************************************************************
///
/// @brief Use of UKRM_Encode_EIB_D to provide DLL interface
///
/// @param [in] sInfoID barcode info ID
/// @param [in] sVersionId barcode version id
/// @param [in] sFormat barcode format
/// @param [in] sClass barcode class ID
/// @param [in] sLicenseNum barcode license number
///
/// @return @arg returns barcode if successful, otherwise returns error
///
/// @LM_Detailed_Description
/// Creates UKRM_Encode_EIB_D object, supplies input and returns result
//
// ******************************************************************************
VARIANT __stdcall CallEncode(LPCSTR sInfoID, LPCSTR sVersionId, LPCSTR sFormat, LPCSTR sClass, LPCSTR sLicenseNum)
{
bool bRC;
class UKRM_Encode_EIB_D stEncodeObject;
char *srtnstring = NULL;
bRC = stEncodeObject.encode((char *) sInfoID, (char *) sVersionId, (char *) sFormat, (char *) sClass, (char *) sLicenseNum);
if(bRC == true)
{
stEncodeObject.get_BarcodeString(&srtnstring);
}
else
{
stEncodeObject.get_ErrorString(&srtnstring);
}
_bstr_t bstrt(srtnstring);
return _variant_t(bstrt).Detach();
}
.def:
LIBRARY "UKRM_EncodeEIB_D"
EXPORTS
encode_eib_d = CallEncode
VERSION 1.0
入力パラメーターで MarshalAs などのさまざまな組み合わせを試したり、文字列の代わりに StringBuilders を試したりしましたが、一方から他方へのメソッド署名に満足していないように聞こえます。
VBAで動作するのはとてもイライラします。
さらに情報が必要な場合は、お問い合わせください。
ありがとう。