【发布时间】:2012-04-20 21:47:54
【问题描述】:
我正在查看来自 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 */
【问题讨论】:
-
char[] 看起来不对。肯定应该是字符串。无论如何,您需要显示 C++ 声明和 C# 调用代码。
-
第 23 个参数的值错误。
-
您仍然没有显示函数的 C++ 声明。无论如何, ToCharArray 不会产生以空字符结尾的字符串。您需要使用字符串而不是 char[]。并正确设置 CharSet。你的代码总是错的,只是在我猜到之前你很幸运。
-
为什么不能显示 C++ 声明?没有那个我们就无能为力了,我正在失去兴趣。如果没有可靠的信息,您将继续得到虚假的答案,导致您大打出手。
-
有一个头文件。你还没有找到。 C++ 示例使用它。我只能猜测字符串参数真的是char*。在这种情况下,您需要在 C# 中使用字符串而不是 char[]。你明白其中的区别吗?这个问题现在真是一团糟。你可能需要重新开始。试着很好地掌握函数在 C++ 中的定义,并去掉问题的虚假部分。