- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试为 modbusm.dll (win-tech.com/html/mbusocx.htm) 创建一个包装器 C# 文件,为此我使用 dumpbin 输出。
文件 modbusm.dll 的转储
File Type: DLL
Section contains the following exports for modbusm.dll
00000000 characteristics
41128817 time date stamp Fri Aug 06 00:48:47 2004
0.00 version
1 ordinal base
27 number of functions
27 number of names
ordinal hint RVA name
1 0 000085BA _AbortTheCall@4
2 1 00003441 _CloseConnection@4
3 2 000033A7 _ConnectASCII@12
4 3 000033E1 _ConnectDanielsASCII@12
5 4 000033C4 _ConnectDanielsRTU@12
6 5 0000338A _ConnectRTU@12
7 6 00001019 _ConnectTCP2@12
8 7 00001000 _ConnectTCP@8
9 8 0000829A _DialCall@8
10 9 00003376 _EnableConnectionCallback@4
11 A 00003342 _EnableModbusCallback@8
12 B 00008123 _GetCallState@8
13 C 00007FD2 _GetLineDeviceName@12
14 D 00003320 _GetPollDelay@0
15 E 00003339 _Get_Modbus_DLL_Revision@0
16 F 000033FE _HookRspNotification@16
17 10 000032ED _InitializeWinSock@0
18 11 0000277C _MBAPWndProc@16
19 12 0000393F _MODBUSResponse@16
20 13 00007EAA _NumberOfLineDevices@0
21 14 00003521 _PollMODBUS@8
22 15 000039F2 _ReadDebugData@16
23 16 00003BA4 _ReadTransparentResponse@16
24 17 0000332A _SetPollDelay@4
25 18 00003313 _UnInitializeWinSock@0
26 19 00003712 _WriteMODBUS@12
27 1A 00003AB3 _WriteTransparentString@12Summary
5000 .data
2000 .rdata
2000 .reloc
1000 .rsrc
C000 .text
我的 C# 包装器是
class MbMasterV7
{
[DllImport("modbusm.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode, EntryPoint = "_ConnectTCP2@12")]
public static extern int ConnectModbusTCP(short Port);
public static string TCPDevice { set; get; }
}
当我运行代码时
MbMasterV7.TCPDevice = "127.0.0.1"; // from demo version of .ocx file converted using tlbimp.exe
MbMasterV7.ConnectModbusTCP(502);
在 Visual Studio 中,我遇到了异常
A call to PInvoke function 'TestApp!TestApp.MbMasterV7::ConnectModbusTCP' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
我已经尝试了所有调用约定并收到相同的错误。可用于 modbus 协议(protocol)的 .Net 库对于我正在使用的新 plc 类型来说不够好。
FILE HEADER VALUES
14C machine (x86)
5 number of sections
41128817 time date stamp Fri Aug 06 00:48:47 2004
0 file pointer to symbol table
0 number of symbols
E0 size of optional header
210E characteristics
Executable
Line numbers stripped
Symbols stripped
32 bit word machine
DLL
OPTIONAL HEADER VALUES
10B magic # (PE32)
6.00 linker version
C000 size of code
A000 size of initialized data
0 size of uninitialized data
94E4 entry point (100094E4)
1000 base of code
D000 base of data
10000000 image base (10000000 to 10016FFF)
1000 section alignment
1000 file alignment
4.00 operating system version
0.00 image version
4.00 subsystem version
0 Win32 version
17000 size of image
1000 size of headers
0 checksum
2 subsystem (Windows GUI)
0 DLL characteristics
100000 size of stack reserve
1000 size of stack commit
100000 size of heap reserve
1000 size of heap commit
0 loader flags
10 number of directories
DF90 [ 357] RVA [size] of Export Directory
D7C8 [ 50] RVA [size] of Import Directory
14000 [ 3E8] RVA [size] of Resource Directory
0 [ 0] RVA [size] of Exception Directory
0 [ 0] RVA [size] of Certificates Directory
15000 [ BC0] RVA [size] of Base Relocation Directory
0 [ 0] RVA [size] of Debug Directory
0 [ 0] RVA [size] of Architecture Directory
0 [ 0] RVA [size] of Global Pointer Directory
0 [ 0] RVA [size] of Thread Storage Directory
0 [ 0] RVA [size] of Load Configuration Directory
0 [ 0] RVA [size] of Bound Import Directory
D000 [ 198] RVA [size] of Import Address Table Directory
0 [ 0] RVA [size] of Delay Import Directory
0 [ 0] RVA [size] of COM Descriptor Directory
0 [ 0] RVA [size] of Reserved Directory
最佳答案
首先,_ConnectTCP2@12
表示将12个字节作为参数传递给函数,即short
(2个字节长)显然是不兼容的。您需要传递 12 个字节作为参数,大概为 3 DWORD
s。
为了冒险,让我们实际反汇编二进制文件,看看那里发生了什么。
所以:ConnectTCP@8
正在接收 2 DWORD
s 作为参数并调用 ConnectTCP2
与 0x1F6
作为第二个参数(实际上是一个短参数)。另外,调用约定是 stdcall .
这些信息足以让我们弄清楚如何调用该函数:
[DllImport("modbusm.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_ConnectTCP2@12")]
public static extern int ConnectModbusTCP(int a, short Port, int b);
可以工作,但会抛出
"Unhandled Exception: System.AccessViolationException:
Attempted to read or write protected memory.
This is often an indication that other memory is corrupt."
这是因为第二个整数(我称之为 b
)实际上是一个指向结构的指针(我只能根据代码猜测它的值)。那么让我们重建结构。根据代码,该结构被访问了五次,如下所示:
Offset Type
0x00 -> INT32
0x04 -> INT32
0x08 -> INT32
0x0C -> INT16
0x10 -> INT32
因此,通过创建以下结构:
struct MbMasterStruct
{
int a;
int b;
int c;
short d;
int e;
}
并将函数重新定义为:
unsafe class MbMasterV7
{
[DllImport("modbusm.dll", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi, EntryPoint = "_ConnectTCP2@12")]
public static extern int ConnectModbusTCP(int a, short Port, MbMasterStruct * b);
}
并按如下方式调用它:
static void Main(string[] args)
{
var structure = new MbMasterStruct();
unsafe
{
MbMasterV7.ConnectModbusTCP(1, 2, &structure);
}
}
它确实有效,而且不会抛出异常。在我的电脑上,它返回 51(当结构和参数都为零时)。
现在您需要了解每个参数并了解如何正确调用该函数。
关于c# - PInvoke 签名与非托管目标签名不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30128753/
我会尝试尽可能详细地描述我的问题,但如果需要更详细的解释,请告诉我。 为了简化,假设我有 3 个 DLL(实际上我有更多,但我猜这不是很重要): managed-1.dll - 托管 DLL(用 C#
我有一个 Tomcat 6 JSF Web 应用程序,我想使用 CDI bean 来设置它。不过,我必须逐渐将项目转换为 CDI。 我的问题是:CDI bean 和传统的 JSF 托管 bean 可以
我计划将 Web 应用程序从使用 JSF 托管 Bean 转换为使用 CDI 托管 Bean。我知道我需要执行以下操作: 在 WEB-INF 中添加一个空 beans.xml 文件。 将所有 JSF
我在裸域上运行我的解析应用程序。 Parse 并没有让我的生活变得轻松。 起初我很难设置它,因为大多数 DNS 托管服务不允许根域上的 CNAME,而 Parse 需要 CNAME。 决定尝试使用 C
如果您使用 Firebase 托管 将请求定向到 云函数 通过重写,“通过”托管的请求流量是否会记入 Firebase 托管 国标转出 ? (忽略 Cloud Function 的计费) 换句话说,
关闭。这个问题是off-topic .它目前不接受答案。 想改善这个问题吗? Update the question所以它是 on-topic对于堆栈溢出。 9年前关闭。 Improve this q
我有一个特定的用例,我正尝试使用 Firebase 托管来解决,它如下: 我正在使用 Gridsome 生成静态网站 在构建之前,Gridsome 使用 Graphql 并从 Headless CMS
您好,我有一个blazor页面,我想在其中显示一个变量。 这个变量从另一个线程(通过Websocket接收数据的另一个线程)获取更新,我想以线程安全的方式显示它: Blazor页面 @page "/n
我想使用 Firebase 托管来托管一个 angular 应用程序,我需要创建一个重定向到另一个 URL 中的一些旧文件。 根据 Firebase 文档,您可以进行基本重定向 "redirects"
我正在尝试找出满足电子学习平台以下要求的最佳方法。 我在其中编辑视频的后端,以便可以将它们彼此链接(例如youtube-comment函数) 用户只能在访问平台时观看视频(不允许下载!) 视频只能通过
已关闭。这个问题是 not about programming or software development 。目前不接受答案。 这个问题似乎不是关于 a specific programming
我想这是一个相当深入的主题,因此任何带有洞察信息的网址也很乐意接受。我一直在使用原生 DirectX,但从未管理过。另一方面,大多数情况下,在开发不需要高级 GPU 渲染的其他类型的应用程序时,我通常
我刚刚将一个网站部署到 Firebase 托管,效果非常好 - 设置非常简单。 但是,我的问题是,有什么方法可以使访问该网站受到身份验证的限制吗?这是一个管理面板,只有我的团队才能访问。有什么方法可以
已关闭。这个问题是 not about programming or software development 。目前不接受答案。 这个问题似乎不是关于 a specific programming
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 要求我们推荐或查找书籍、工具、软件库、教程或其他场外资源的问题对于 Stack Overflow 来说是
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 6 年前。
我刚刚将一个网站部署到 Firebase 托管,它运行良好 - 设置非常简单。 但是,我的问题是,有什么方法可以通过身份验证限制对网站的访问?这是一个只有我的团队才能访问的管理面板。有什么方法可以用密
如果我想托管一个对公众用处不大的应用程序(例如,一个将点打印到控制台的程序,它们的数量取决于现在的时间),我喜欢在启动板中的方式不必乱扔全局托管站点的命名空间并用诸如 HourDot 之类的名称填充它
我是一名优秀的程序员,十分优秀!