Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过互操作接收字符串_C#_C_Interop_Stringbuilder - Fatal编程技术网

C# 通过互操作接收字符串

C# 通过互操作接收字符串,c#,c,interop,stringbuilder,C#,C,Interop,Stringbuilder,我很难从我编写的一些c代码中获取字符串 首先是一些通常不相关的背景信息:我想从TAPI API接收用户可读的TAPI TSP字符串。我已经实现了一个半可行的TAPI解决方案,该解决方案依赖于将驱动程序名称与存储的字符串相匹配,但我想将其改为在永久线路id上工作,因为我们的一个客户的(阿尔卡特)PBX拒绝以任何其他方式工作 在C中,我将头文件中的函数定义为: __declspec(dllexport) void GetDeviceName(long DeviceId, wchar_t* Devic

我很难从我编写的一些c代码中获取字符串

首先是一些通常不相关的背景信息:我想从TAPI API接收用户可读的TAPI TSP字符串。我已经实现了一个半可行的TAPI解决方案,该解决方案依赖于将驱动程序名称与存储的字符串相匹配,但我想将其改为在永久线路id上工作,因为我们的一个客户的(阿尔卡特)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()中设置。我还将返回类型设置为
void
,希望这也会影响某些东西(请参阅半有用的mono文章以获得部分伪科学解释)

可以这么说:

StringBuilder name = new StringBuilder();
name.EnsureCapacity(100);
long n = 0;
GetDeviceName(n, name);
我将调试器附加到正在运行的进程,设置一个断点,并在C代码中注意到StringBuilder在某种程度上被扭曲了,并作为空指针提供给非托管代码

随后在C#中抛出AccessViolationException

出什么事了


删除long参数会有所帮助。我可以将“abc”添加到C中的DeviceName参数中。不过,我需要那个长变量!我做了什么错事或者是不安,是因为有这么长的参数而导致崩溃?< /P> < P> C++ >代码>长< /C> > 32位,C < <代码>长< /C> > 64位,不是吗?因此,你需要使用第一个参数的<代码> int /代码>。< /p> < p> C++ >代码>长< /C> > 32位,C < <代码>长< /C> >是64位,不是吗?因此,您需要对第一个参数使用
int

在32位平台上
long
在.NET中宽8字节(64位),在本机代码中宽4字节(32位)。您需要像这样更改P/Invoke方法:

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

这样,C#
int
和C
long
在32位平台上具有相同的宽度。

在32位平台上
long
在.NET中宽8字节(64位),在本机代码中宽4字节(32位)。您需要像这样更改P/Invoke方法:

[DllImport("SBW.Tapi.TapiInterop.dll", CharSet = CharSet.Auto)]
static extern void GetDeviceName(int DeviceId, StringBuilder DeviceName);
这样,C#
int
和C
long
在32位平台上具有相同的宽度

我想要那个长变量

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

我想要那个长变量


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

无需这样做。StringBuilder被自动定义为[In,Out],现在你编辑了一些完全不同的答案,把所有人都弄糊涂了,这让我的评论变得荒谬:)对不起。但是每个人都看到它被编辑了,任何人都可以查看历史…;)没必要。StringBuilder被自动定义为[In,Out],现在你编辑了一些完全不同的答案,把所有人都弄糊涂了,这让我的评论变得荒谬:)对不起。但是每个人都看到它被编辑了,任何人都可以查看历史…;)