Gang,
I'm using a third-party API written in (what looks like) MFC C++. My application is a WinForms app in C#. The API's company has a C# demo application, and I used their code verbatim. The relevant code looks like this...
API's C++ Function:
int PASCAL CppFunction(BYTE *pbAdapterID, BYTE *pbTargetID, char *pcVendor, char *pcProduct, char *pcRelease, int iMessageBox)
{
// The function definition is all I can see in the API's documentation
}
The DllImport Statement:
[DllImport("api.dll")]
extern public static int CppFunction(ref byte pbAdapter, ref byte pbTargetID, string pcVendor, string pcProduct, string pcRelease, int iMessageBox);
My C# Logic:
public void CallCppFunction()
{
try
{
int result = 0;
string strVendorBuffer = string.Empty;
string strProductBuffer = string.Empty;
string strReleaseBuffer = string.Empty;
string strSerial = string.Empty;
byte bAdapt = 0;
byte bTarg = 0;
result = CppFunction(ref bAdapt, ref bTarg, strVendorBuffer, strProductBuffer, strReleaseBuffer, 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
This is the code as it exists in their C# sample. When run, it crashes with a "FatalExecutionEngineError" even in a try/catch.
I don't know PInvoke very well, but don't those variables have to be marshaled as an unmanaged type? Any help would be appreciated.
I am taking a wild guess here, but I am pretty sure it will be the right answer
Lets take a look to the function definition:
int PASCAL CppFunction(
BYTE *pbAdapterID,
BYTE *pbTargetID,
char *pcVendor,
char *pcProduct,
char *pcRelease,
int iMessageBox);
And the corresponding DllImport declaration:
[DllImport("api.dll")]
extern public static int CppFunction(
ref byte pbAdapter,
ref byte pbTargetID,
string pcVendor,
string pcProduct,
string pcRelease,
int iMessageBox);
There are a lot of parameters there, some of them caught my attention:
char *pcVendor,
char *pcProduct,
char *pcRelease,
They are not passed by reference, are they being modified by the library?
Note: That why I asked you to give details about the function.
I that's the case, you cannot marshal strings because the datatype string is immutable, you must use the StringBuilder
class, just make sure the StringBuilder
has enough Capacity.
int result = 0;
StringBuilder strVendorBuffer = new StringBuilder(1024); // up to 1024 chars
StringBuilder strProductBuffer = new StringBuilder(1024); // up to 1024 chars
StringBuilder strReleaseBuffer = new StringBuilder(1024); // up to 1024 chars
StringBuilder strSerial = string.Empty;
byte bAdapt = 0;
byte bTarg = 0;
result = CppFunction(ref bAdapt, ref bTarg, strVendorBuffer, strProductBuffer, strReleaseBuffer, 0);