3

我正在查看来自 sourceforge 的示例项目,用于链接到 TSAPI(不是 TAPI)电话系统 - http://tsapi.sourceforge.net/

我的开发环境是 32 位 Windows XP,项目设置为目标 x86。

这可以正常运行,因为它可以针对 .Net 2 运行,但我需要针对 .Net 4 运行。当我更改框架并运行第一个函数时,返回 -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);

还提供了一个 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 函数“Mojo!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 */
4

3 回答 3

0

您声明的字符串参数char[]总是错误的。我猜你在早期的 .net 版本中碰巧侥幸逃脱了。

C++ 代码将这些参数声明为char*,即指向以空字符结尾的字符数组的指针。在 C# 代码中声明这些参数的正确方法是 as string。p/invoke marshaller 将负责将您的 C# 字符串转换为 C 字符串,您可以删除所有虚假ToCharArray()代码。

于 2012-04-21T15:38:39.200 回答
0

考虑到您在谈论 4.0,我,也很难从提供的问题中推断出来,您在 4.0 下运行的应用程序也在 64 位操作系统下运行。

如果,那么,失败是绝对合理的,因为你的目标是csta32.dllDLL 并使用类似的参数UInt32

提出解决此问题的解决方案的第一步是

  • 选择要从中导入的正确库
  • 替换Uint32uint,因此该类型的正确维度将由运行时选择。

但是这些自然是尝试,应该尊重必须声明导入的正确方法的正确签名。

如果这不是您要的,或者不是您的问题,请澄清。

于 2012-04-20T21:58:07.897 回答
0

答案是将char[]修改为字符串。然后这适用于 .Net 4.0 - 如果保留为 char [] 它返回 -2 ( ACSERR_BADPARAMETER )。

因此,2.0 必须处理此问题,因为 DLLImport 不需要此更改以在该版本的框架上工作。

于 2012-04-21T15:08:10.567 回答