2012-04-20 14 views
3

我正在查看sourceforge的示例項目,以鏈接到TSAPI(非TAPI)電話系統 - http://tsapi.sourceforge.net/.Net 4導致DLLImport函數返回失敗代碼,.Net 2,3或3.5不是

我的開發環境是32位Windows XP,並且該項目設置爲x86。

這工作正常提供運行對.Net 2,但我需要運行.Net 4.當我更改框架並運行第1個函數返回-1表示失敗。

函數定義爲:

[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); 

C#代碼(從示例項目中提取)用於調用此功能:

// 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++示例應用程序也是在該函數調用中提供是:

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. 

如果我將DLLImport更改爲

[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); 

我得到的運行時錯誤

檢測PInvokeStackImbalance 消息:對PInvoke的功能 '!魔CSTA :: acsOpenStream' 呼叫具有不平衡堆棧。這很可能是因爲託管的PInvoke簽名與非託管目標籤名不匹配。檢查PInvoke簽名的調用約定和參數是否與目標非託管簽名相匹配。

的Avaya不提供頭文件 - 文件表示該功能的定義是:

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 */ 
+2

你運行64位機嗎? – Tigran 2012-04-20 21:52:59

+0

char []看起來不對。應該是確定的字符串。無論如何,你需要顯示C++聲明和C#調用代碼。 – 2012-04-20 21:57:39

+0

第23個參數的值錯誤。 – 2012-04-20 22:18:26

回答

0

您聲明爲char[]的字符串參數始終是錯誤的。我猜你在早期的.net版本中偶然會遇到這種情況。

C++代碼聲明這些參數爲char*,即指向空終止字符數組的指針。在C#代碼中聲明這些參數的正確方法是string。 p/invoke編組將負責將C#字符串轉換爲C字符串,並且您可以刪除所有僞造的ToCharArray()代碼。

0

考慮到你所談論的4.0,我,也很難演繹形式提供的問題,您在4.0下運行的應用程序也在64位操作系統下運行。

如果故障是絕對正確的,因爲你的目標是csta32.dll DLL和 使用類似參數UInt32

第一步驟,以推進解決方案解決這個問題,是

  • 選擇正確的庫從
  • 分別代替Uint32導入與uint,所以該類型的正確尺寸將被運行時進行選擇。

但是,這些都是自然而然的嘗試,應該尊重必須聲明導入的正確方法的正確簽名。

如果這不是你要求的,或者這不是你的問題,請澄清。

+2

uint和UInt32在所有平臺上都是32位寬。 – 2012-04-20 22:00:01

+0

我在32位XP上運行,平臺目標是x86。如前所述,對我而言,不尋常的部分是它可以工作,直到您更改目標框架,這意味着您應該如何使用3.5和4.0之間的DLLImport(我不知道)發生了什麼變化。 – 2012-04-20 22:00:49

+0

如果您突然切換到x64,則DLL將無法加載。 – 2012-04-20 22:02:45

0

答案是將char []修改爲字符串。然後在.Net 4.0上運行 - 如果保留爲char [],則返回-2(ACSERR_BADPARAMETER)。

因此,2.0必須處理此問題,因爲DLLImport無法在該版本的框架上使用此更改。

相關問題