c# - 通过互操作接收字符串

标签 c# c interop stringbuilder

我无法从我编写的某些 C 代码中取回字符串。

首先是一些通常未实现的背景信息:我想从 TAPI API 接收 TAPI TSP 的用户可读字符串。我已经实现了一个半可行的 TAPI 解决方案,该解决方案依赖于将驱动程序名称与存储的字符串匹配,但我想将其更改为在永久线路 ID 上工作,因为我们的一位客户有一个 (Alcatel) PBX 拒绝以任何其他方式工作.

在 C 中,我将头文件中的函数定义为:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName);

函数是这样写的:

__declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* DeviceName)
{
    //tapi code here...

    //copy the string to DeviceName
    wcscpy(DeviceName, (wchar_t*)((char *)devCaps + devCaps->dwLineNameOffset));
}

如上所述,这最终会做一些有用的事情,但现在如果 abc 放在我的 wchar_t*/StringBuilder 中并且我可以在 C# 中看到它,我会很高兴。

在 C# 中,我将函数定义为:

    [DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
    static extern void GetDeviceName(long DeviceId, StringBuilder DeviceName);

我将 DeviceName 定义为 StringBuilder,因为字符串是不可变的,我希望 DeviceName 在 C ( This is recommended by MS) 中设置。我还将返回类型设置为 void,希望这也会影响某些东西(请参阅 this 半有用的单文文章以获取部分伪科学解释)。

这样调用它:

StringBuilder name = new StringBuilder();
name.EnsureCapacity(100);
long n = 0;
GetDeviceName(n, name);

我将我的调试器附加到正在运行的进程,设置一个断点,并在 C 代码中注意到 StringBuilder 以某种方式变态并作为空指针提供给非托管代码。

随后在 C# 中抛出 AccessViolationException。

出了什么问题?

删除长参数会有所帮助。我可以在 C 中将“abc”添加到我的 DeviceName 参数中。但是我想要那个长变量!我做错了什么或因为在那里有那么长的参数而导致崩溃而感到不安?

最佳答案

I want that long variable however

那么你应该在C中定义参数为long long。正如 Lucero 指出的那样,C++ 中的 long 是 32 位,而 C# 中的 long 是 64 位。因此,如果您在 C 函数需要 32 位值的地方传递 64 位值,该函数将读取额外的 32 位作为第二个参数,这显然会导致缓冲区地址错误...

关于c# - 通过互操作接收字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2027022/

相关文章:

c# - Wpf InkCanvas 将笔画保存为 svg

c - 在 C++ 中,abs( *a - *b) 不返回负数的绝对值

c - gtkmozembed 段错误

c# - P/Invoke 声明不应是安全关键的

c# - 如何将 void* 转换为可在 C# 中使用的类型? C DLL 和 C# 之间的互操作性

c# - 从 .NET 2.0 向下迁移到 .NET 1.1 - DllImport 不再有效

c# - Control.ControlCollection 类中的 "Control"是什么?

c# - WCF 模拟不是模拟管理员

c# - JavaScript 函数阻止 C# 函数被执行?

c - C 中指针的区别