2010-01-08 88 views
1

我无法从我写的一些c代码中取回字符串。通过interop接收字符串

首先是一些通常不相关的背景信息:我想从TAPI API接收用户可读的TAPI TSP字符串。我已经实施了一个半可行的TAPI解决方案,依靠匹配的驱动程序名称来存储字符串,但是想要改变这种方式来处理permanant行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); 

我定义设备名称作为一个StringBuilder因为字符串是immuatable和我想要的设备名称,以C(This is recommended by MS)来设置。我还设置了返回类型为void的渺茫希望,​​这也会影响某些内容(请参阅this半赞助性单文章以获得部分伪科学解释)。

,并呼吁它这样:

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

我我的调试器附加到正在运行的进程,设置断点,并通知在C代码,不知怎的,StringBuilder的是变态的,并提供给非托管代码作为空指针。

AccessViolationException随后在C#中抛出。

出了什么问题?

删除长参数有帮助。我可以在C中的DeviceName参数中添加“abc”,但是我想要这个长变量!我在做什么错误或沮丧以便通过在那里设置那个长参数来强制崩溃?

回答

1

在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个平台的宽度相同。

1

C++ long是32位,C#long是64位,不是吗?因此,您需要使用int作为第一个参数。

+0

没有必要。 StringBuilder的是自动定义为输入,输出] – 2010-01-08 11:05:05

+0

现在你已经走了,并通过编辑答案完全不同的东西迷惑大家,从而使我的意见无厘头:) – 2010-01-08 14:30:31

+0

对此深感抱歉。但是每个人都看到它已经被编辑了,任何人都可以检查历史......;) – Lucero 2010-01-11 09:14:03

2

我想要变长但是

那么你应该在C作为long long定义参数。正如Lucero指出的那样,C++中的长整型是32位,而C#中的长整型是64位。所以,如果你通过一个64位值,其中C函数需要一个32位的值,该函数读取额外的32位作为第二个参数,这显然会导致一个错误的地址缓冲...