c# - P/Invoke 有时会导致 Win32 1008 Error with StringBuilder parameters

标签 c# interop pinvoke

我有一个 DLL,我需要从中 P/调用以下 C 方法:

int DAStart(
    HANDLE hOpen,
    char* IPAddress,
    int IPPort,
    int threadPriority,
    char* name,
    char* password,
    char* userName)

使用 P/Invoke Assistant 和我自己的研究,我得出了以下 C# 签名:

[DllImportAttribute("<libName>", EntryPoint="DAStart")]  
static extern  int DAStart(  
    IntPtr hOpen,  
    [MarshalAs(Unmanaged.LPStr)] StringBuilder IPAddress,
    int IPPort,
    int threadPriority, 
    [MarshalAs(Unmanaged.LPStr)] StringBuilder name, 
    [MarshalAs(Unmanaged.LPStr)] StringBuilder password,   
    [MarshalAs(Unmanaged.LPStr)] StringBuilder userName);

现在,我按以下方式进行调用:

int port = 3000;
int threadPriority = 20;

DAStart(
    this.nativeDllHandle, // an IntPtr class field  
    new StringBuilder("10.0.10.1"),
    int port,
    int threadPriority,
    new StringBuilder("admin"),
    new StringBuilder("admin"),
    new StringBuilder("admin"));

现在,有时这工作得很好,但我遇到了 Win32 错误 1008 - 试图引用一个不存在的 token 在随后调用此库时。

会不会是我的 StringBuilder 对象被垃圾回收,因此如果 native 代码尝试使用它,引用将不再存在?我应该为他们每个人保留一份引用吗?

在这种情况下,IntPtr 是否是传递我的字符串的更好解决方案?

** 更新 **

这是我拥有的 DAStart 的所有 API 文档:

输入
HANDLE hInfo DAOpen返回的句柄
char *IPAdress_in TMEE服务器的IP地址
int IPPort TMEE Server 控制台端口(默认为 3000 端口)
int threadPriority 发送文件线程的线程优先级。
char *name 未在硬件 DLL 中使用
char *password 不用于硬件 DLL
char *username 不在硬件 DLL 中使用

返回
错误_成功 0
ERROR_BAD_HANDLE -1
ERROR_BIND_FAILED -10

评论
DAStart API 将客户端 dll 连接到事件的 TMEE 服务器服务。客户端线程以设置为 threadPriority 参数的优先级启动。 IP 地址参数必须设置为 TMEE 服务器的地址。端口参数必须设置为 TMEE 服务器监听控制台连接的端口(控制台使用的默认端口为 3010)。控制台线程以设置为 threadPriority 参数的优先级启动。

最佳答案

在注释中,您指出 DLL 获取 char* 指针的副本(而不是字符串的内容),然后在 之后修改字符串的内容> DAStart 返回。

面对这种非常规的界面设计,您唯一的选择就是负责字符串参数的编码。您不能使用 StringBuilder,因为传递给 native 代码的 char* 仅在 pinvoke 调用期间有效。不能相信它在 pinvoke 调用返回后有效。

所以您唯一的解决方案是将字符串参数作为 IntPtr 传递。使用 Marshal.StringToHGlobalAnsi 分配内存。将生成的 IntPtr 传递给 DAStart。当您确定 DLL 已使用指针完成时,使用 Marshal.FreeHGlobal 解除分配。

关于c# - P/Invoke 有时会导致 Win32 1008 Error with StringBuilder parameters,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9604779/

相关文章:

c# - 如何获得指向 C 函数的指针?

c# - Entity Framework 如何管理数据库连接?

c# - 如果 PictureBox 小于 Picture,则使 Image 适应 PictureBox

c# - session 超时时如何在登录页面显示错误消息

c# - Word 2010 互操作 : Show the "Save As" dialog

java - 为什么我不能在 clojure 中绑定(bind) defrecord?

c# - ASP.NET MVC ViewModel 属性为空

c# - 如何使用 SafeHandle 或解决方法获取方法的 GetFunctionPointerForDelegate

c# - 如何以编程方式使用 PIN 码登录 Windows

c# - 使用 Visual Studio 构建 C++ DLL - Linux 上的 PInvoke