I have a C++ dll that I am trying to get working in my C# project (I know nothing about C++/C but do have the source and can open and build it in VS2013)
The dll came with working examples in Excel VBA but I cant get it working in C#.
The error I keep coming up against is...
Additional information: A call to PInvoke function 'RMTest!RMTest.PInvokeTest::encode_eib_d' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged
My C# test code is as follows...
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);
}
}
For reference, the working example in Excel, the VBA is as follows...
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
The relevant snippet of code in the C++ dll (as far as I can tell) is as follows...
Header (.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
I have tried various combinations of MarshalAs etc on the input parameters as well as trying StringBuilders instead of strings, but it sounds as if it isn't happy with the method signature from one to the other.
So frustrating that it works in VBA.
If you need anymore info please ask.
Thanks.