c# - Cisco TSP - 在 C# 中从 32 位到 64 位的工具迁移
问题描述
目前我有一个问题,我应该迁移一个通过 Cisco TAPI 通信的工具。目前它在 32 位编译下运行。
如果我将编译集切换为 64 位并将 nuget 包“ATAPI”(由 Mark Smith <2> 编写)更新为 64 位版本。
如果我构建并测试它,TAPI 日志会写入 dwSize 不匹配。我尝试为 CiscoDevSpecific-structs 设置一个明确的 StructLayout(如此处建议的<1>)。但同样的错误出现在日志文件中。
错误信息
15:44:51.105 | TSPI_lineGetAddressStatus() TSPI_lineGetAddressStatus returns = 0x00000000
15:44:51.106 | TSPI_lineDevSpecific()
dwRequestID: 0x000105AF hdLine: 0x175B4B30 dwAddressID: 0x00000000 hdCall: 0x00000000 lpParams: 0x202D6E98 dwSize: 32
15:44:51.106 | CSelsiusTSPLine::DevSpecific() [0x00000D32] *ERROR* dwSize mis-match 0x00000020
15:44:51.106 | TSPI_lineDevSpecific() TSPI_lineDevSpecific returns = 0x80000048
例如 StartCallMonitoring 的结构看起来像
[StructLayout(LayoutKind.Explicit, Size = 32)]
public struct CiscoLineDevSpecificStartCallMonitoring
{
[FieldOffset(0)]
public int m_MsgType;
[FieldOffset(8)]
public int m_PermanentLineID;
[FieldOffset(16)]
public int m_MonitorMode; //0= NONE, 1=SILENT, 2=WHISPER, 3=ACTIVE
[FieldOffset(24)]
public int m_ToneDirection; //0=LOCALONLY, 1=REMOTEONLY, 2=BOTH, 3=NOTLOCALORREMOTE
}
初始化像
var cisco = new CiscoLineDevSpecificStartCallMonitoring
{
m_MsgType = (int)CiscoLineDevSpecificType.SLDST_START_CALL_MONITORING,
m_PermanentLineID = permanentIdOfTargetLine,
m_MonitorMode = (int)monitorMode,
m_ToneDirection = (int)PlayToneDirection.PlayToneDirectionNoLocalOrRemote
};
字节数的计算如下:
private static byte[] GetBytes(object msg)
{
var size = Marshal.SizeOf(msg);
var arr = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(msg, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
感谢您的回复。
<1> https://community.cisco.com/t5/collaboration-documents/tsp-x64-devspecific-dword-size-mismatch-problem/ta-p/3613828 <2> https://github.com/markjulmar /atapi.net
解决方案
我遇到同样的问题。我没有完全解决它,但我想我可以提供一些信息来帮助。我知道这不是一个完整的解决方案,但在 7 个月内没有人做出回应。
第一点是我们必须编组的结构。我无法反编译 cisco 类(无权访问它们),但如果您查看 cisco dev guide:
class CCiscoLineDevSpecific
{
public:CCicsoLineDevSpecific(DWORDmsgType);
virtual~CCiscoLineDevSpecific();
DWORD GetMsgType(void) const {return m_MsgType;}
void* lpParams() {
return &m_MsgType;
}
virtual DWORDdwSize()= 0;
private: DWORDm_MsgType;
};
//and the class we are using is:
class CCiscoLineDevSpecificStartCallMonitoring: public CCiscoLineDevSpecific
{
public:
CCiscoLineDevSpecificStartCallMonitoring () :
CCiscoLineDevSpecific(SLDST_START_CALL_MONITORING) {}
virtual ~ CCiscoLineDevSpecificStartCallMonitoring () {}
DWORD m_PermanentLineID ;
DWORD m_MonitorMode;
DWORD m_ToneDirection;
// subtract out the virtual function table pointer
virtual DWORD dwSize(void) const {return sizeof(*this)-4;}
} ;
因此涉及继承,然后需要一些用于填充/对齐的字节。
第二点是即使在 x64 操作系统中,DWORD 也不是 8 字节大小而是 4 字节。
考虑到这一点,我的建议结构应该是这样的:
[StructLayout(LayoutKind.Explicit, Size = 24)]
public struct CCiscoLineDevSpecificStartCallMonitoring_64
{
[FieldOffset(0)]
public uint msgType;
[FieldOffset(4)]
public uint padding;
[FieldOffset(8)]
public uint m_PermanentLineID;
[FieldOffset(12)]
public uint m_MonitorMode;
[FieldOffset(16)]
public uint m_ToneDirection;
[FieldOffset(20)]
public uint m_padding;
public byte[] ToBytes()
{
Byte[] bytes = new Byte[Marshal.SizeOf(typeof(CCiscoLineDevSpecificStartCallMonitoring_64))];
GCHandle pinStructure = GCHandle.Alloc(this, GCHandleType.Pinned);
try
{
Marshal.Copy(pinStructure.AddrOfPinnedObject(), bytes, 0, bytes.Length);
return bytes;
}
finally
{
pinStructure.Free();
}
}
}
有了这个结构,我可以得到:
20:50:31.480 | LineCallStartMonitoringRequest::Trace
dwCallingAddressOffset =0x00000058
dwCallingAddressSize =4
CallingAddress =870
dwDestAddressOffset =0x0000005C
dwDestAddressSize =4
DestAddress =984
dwDeviceNameOffset =0x00000060
dwDeviceNameSize =10
DeviceName =CSFCAT984
dwCallID =0x023B4DA2
dwTone=3
dwMonitorMode =1
我不是 C++ 开发人员,但我准备了一个小型 C++ 程序来检查派生类的元素偏移量并找到这些填充。我不知道他们是从哪里来的。
正如我所提到的,它仍然无法在我的基础设施中工作。在此之后,我收到:
20:50:31.497 |-->CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D
20:50:31.497 | CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D lResult = 0x80000049
20:50:31.497 |<--CSelsiusTSPLine::MapCtiToTspErrorCode(), CTI error code - 0x8CCC009D
但这可能是因为配置问题。任何情况下,我都想提供这种观点,以便我们能够尽快达成完整的解决方案。
推荐阅读
- ssas - 当您有两个或多个具有相同键值但名称不同的属性时,如何建立属性关系和层次结构?
- sql - 在 Django 中,如何查询所有相关对象对于某个字段具有相同的值?
- c++ - c++ directx 9 使用 IDirect3DDevice9::SetSamplerState 的文本过滤错误
- android - 如何在 RecyclerView 的类中访问方法内的资源
- c - 这个 FFT 函数的输出有什么意义?
- c - 为什么char值增加3?
- java - 如何在 onClick 事件和 Activity 更改后将 textView 设置为可见?
- azure - 跟踪 Azure DevOps 构建活动
- ruby-on-rails - 将日期字符串转换为时区特定格式
- email - google 应用程序脚本:file.setOwner() 未在 Google Drive 中转移所有权