.Net 4导致DLLImport函数返回失败代码,.Net 2,3或3.5不是
我正在查看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 */
您声明为char[]
的字符串参数始终是错误的。我猜你在早期的.net版本中偶然会遇到这种情况。
C++代码声明这些参数为char*
,即指向空终止字符数组的指针。在C#代码中声明这些参数的正确方法是string
。 p/invoke编组将负责将C#字符串转换为C字符串,并且您可以删除所有伪造的ToCharArray()
代码。
考虑到你所谈论的4.0,我想,也很难演绎形式提供的问题,您在4.0下运行的应用程序也在64位操作系统下运行。
如果故障是绝对正确的,因为你的目标是csta32.dll
DLL和 使用类似参数UInt32
。
第一步骤,以推进解决方案解决这个问题,是
- 选择正确的库从
- 分别代替
Uint32
导入与uint
,所以该类型的正确尺寸将被运行时进行选择。
但是,这些都是自然而然的尝试,应该尊重必须声明导入的正确方法的正确签名。
如果这不是你要求的,或者这不是你的问题,请澄清。
uint和UInt32在所有平台上都是32位宽。 – 2012-04-20 22:00:01
我在32位XP上运行,平台目标是x86。如前所述,对我而言,不寻常的部分是它可以工作,直到您更改目标框架,这意味着您应该如何使用3.5和4.0之间的DLLImport(我不知道)发生了什么变化。 – 2012-04-20 22:00:49
如果您突然切换到x64,则DLL将无法加载。 – 2012-04-20 22:02:45
答案是将char []修改为字符串。然后在.Net 4.0上运行 - 如果保留为char [],则返回-2(ACSERR_BADPARAMETER)。
因此,2.0必须处理此问题,因为DLLImport无法在该版本的框架上使用此更改。
你运行64位机吗? – Tigran 2012-04-20 21:52:59
char []看起来不对。应该是确定的字符串。无论如何,你需要显示C++声明和C#调用代码。 – 2012-04-20 21:57:39
第23个参数的值错误。 – 2012-04-20 22:18:26