代码之家  ›  专栏  ›  技术社区  ›  Matt Jacobsen

通过互操作接收字符串

  •  1
  • Matt Jacobsen  · 技术社区  · 16 年前

    首先是一些通常不相关的背景信息:我想从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中看到这一点。

        [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在某种程度上被扭曲了,并作为空指针提供给非托管代码。

    出什么事了?

    3 回复  |  直到 16 年前
        1
  •  1
  •   Laurent Etiemble    16 年前

    long

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

    这边,C# int 和C 长的

        2
  •  2
  •   Thomas Levesque    16 年前

    我想要那个长变量

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

        3
  •  1
  •   Lucero    16 年前

    long 是32位,C# 长的 int