Friday, April 20, 2012

.Net 4 causes DLLImport function to return failure code, .Net 2, 3 or 3.5 does not

I am looking at a sample project from sourceforge for linking to a TSAPI (not TAPI) telephone system - http://tsapi.sourceforge.net/ .



My development environment is 32bit Windows XP and the project is set to target x86.



This works fine as provided to run against .Net 2 but I need to run against .Net 4. When I change the framework and run the 1st function returns -1 indicating failure.



The function definition is:



[DllImport("csta32.dll")]
public static extern int acsOpenStream(ref UInt32 acsHandle, int invokeIDType, UInt32 invokeID, int streamType, char[] serverID, char[] loginID, char[] passwd, char[] applicationName, int acsLevelReq, char[] apiVer, ushort sendQSize, ushort sendExtraBufs, ushort recvQSize, ushort recvExtraBufs, ref PrivateData_t priv);


The c# code (extracted from sample project) for calling this function is:



    // The public method to open the ACS stream
public bool open(string strLoginId, string strPasswd, string strServerId)
{
// Convert the parameters to character arrays
char[] serverId = strServerId.ToCharArray();
char[] loginId = strLoginId.ToCharArray();
char[] passwd = strPasswd.ToCharArray();

// Define the initial set of variables used for opening the ACS Stream
int invokeIdType = 1;
UInt32 invokeId = 0;
int streamType = 1;
char[] appName = "Mojo".ToCharArray();
int acsLevelReq = 1;
char[] apiVer = "TS1-2".ToCharArray();
ushort sendQSize = 0;
ushort sendExtraBufs = 0;
ushort recvQSize = 0;
ushort recvExtraBufs = 0;

// Define the mandatory (but unused) private data structure
Csta.PrivateData_t privData = new Csta.PrivateData_t();
privData.vendor = "MERLIN ".ToCharArray();
privData.length = 4;
privData.data = "N".ToCharArray();

// Define the event buffer pointer that gets data back from the TServer
ushort numEvents = 0;
Csta.EventBuf_t eventBuf = new Csta.EventBuf_t();
ushort eventBufSize = (ushort)Csta.CSTA_MAX_HEAP;

// Open the ACS stream
try
{
int openStream = Csta.acsOpenStream(ref acsHandle, invokeIdType, invokeId, streamType, serverId, loginId, passwd, appName, acsLevelReq, apiVer, sendQSize, sendExtraBufs, recvQSize, recvExtraBufs, ref privData);


A C++ sample application is also provided in which the function call is:



m_nRetCode = acsOpenStream(&m_lAcsHandle            // Handle for ACS Stream 
, APP_GEN_ID // APP_GEN_ID indicates Application generated invokeID's
, (InvokeID_t)m_ulInvokeID // By default 1
, ST_CSTA
, (ServerID_t *)(serverID) // AE Server Name
, (LoginID_t *)(loginID) // CTI LoginID
, (Passwd_t *)(password) // CTI LoginID password
, (AppName_t *)"TSAPI_AgentView"
, ACS_LEVEL1
, (Version_t *) "TS1-2" // private Data version in use 8 in our case
, 10
, 5
, 50
, 5
, (PrivateData_t *)&m_stPrivateData); // private Data.


If I change the DLLImport to



[DllImport("csta32.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern int acsOpenStream(ref UInt32 acsHandle, int invokeIDType, UInt32 invokeID, int streamType, char[] serverID, char[] loginID, char[] passwd, char[] applicationName, int acsLevelReq, char[] apiVer, ushort sendQSize, ushort sendExtraBufs, ushort recvQSize, ushort recvExtraBufs, ref PrivateData_t priv);


I get the runtime error



PInvokeStackImbalance was detected
Message: A call to PInvoke function 'Mojo!Csta::acsOpenStream' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.



Avaya do not provide the header file - the documentation indicates the function definition to be:



RetCode_t acsOpenStream(
ACSHandle_t *acsHandle, /* RETURN */
InvokeIDType_t invokeIDType, /* INPUT */
InvokeID_t invokeID, /* INPUT */
StreamType_t streamType, /* INPUT */
ServerID_t *serverID, /* INPUT */
LoginID_t *loginID, /* INPUT */
Passwd_t *passwd, /* INPUT */
AppName_t *applicationName, /* INPUT */
Level_t acsLevelReq /* INPUT */
Version_t *apiVer, /* INPUT */
unsigned short sendQSize, /* INPUT */
unsigned short sendExtraBufs, /* INPUT */
unsigned short recvQSize, /* INPUT */
unsigned short recvExtraBufs /* INPUT */
PrivateData_t *privateData); /* INPUT */


Any help would be appreciated





No comments:

Post a Comment