【问题标题】:P/Invoking function via a mangled name通过重命名的 P/Invoking 函数
【发布时间】:2011-06-15 19:48:47
【问题描述】:

我正在尝试在 windows ce 6.0 环境中的 .net cf 3.5 中调用非托管 c++ dll 中的函数。

结构体定义为:

typedef struct TagOperatorInfo
{
    DWORD dwMode;       
    DWORD dwFormat;     //Operator name format
    DWORD dwAct;        //Network type(Available in 3G module£ºGSM or 3G),
    TCHAR szOper[32];   
}OperatorInfo,*LPOperatorInfo;

函数调用是:

BOOL GetCurOperatorInfo(LPOperatorInfo pinfo);

我在.net中定义了TagOperatorInfo如下:

[System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential, CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    public struct TagOperatorInfo
    {

        /// DWORD->unsigned int
        public uint dwMode;

        /// DWORD->unsigned int
        public uint dwFormat;

        /// DWORD->unsigned int
        public uint dwAct;

        /// TCHAR[32]
        [System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst = 32)]
        public string szOper;
    }

在看到一些文章和 msdn 文档后,我将本机函数称为:

[System.Runtime.InteropServices.DllImportAttribute(gsmaAdapterDLLName, EntryPoint = "#30", CallingConvention = CallingConvention.Winapi)]
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
    internal static extern bool GetCurOperatorInfo([MarshalAs(UnmanagedType.LPStruct)] ref NativeHelper.TagOperatorInfo operatorInfo);

注意:我使用序号定义的入口点调用该函数,因为 c++ 破坏了名称。

我遇到的问题是我总是抛出 notSupportedException。我不明白,因为 ref 参数应该给它指向结构的指针。

调用它的我的 .net 函数是:

/// <summary>
    /// Gets the current operator information.
    /// </summary>
    /// <param name="operatorInfo">The operator info.</param>
    /// <returns></returns>
    public static bool GetOperatorInformation(out NativeHelper.TagOperatorInfo operatorInfo)
    {
        operatorInfo = new NativeHelper.TagOperatorInfo();

        if (NativeImports.GetCurOperatorInfo(ref operatorInfo) == true)
        {
            return true;
        }
        else
        {
            return false;
        }

    }

为此我缺少什么。

更新

新的.Net Compact Framework方法调用

[System.Runtime.InteropServices.DllImportAttribute(gsmaAdapterDLLName, EntryPoint = "?GetCurOperatorInfo@CGSMAdapter@@YAHPAUTagOperatorInfo@@@Z", CallingConvention = CallingConvention.Winapi)]
    [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
    internal static extern bool GetCurOperatorInfo([MarshalAs(UnmanagedType.LPStruct)]ref NativeHelper.TagOperatorInfo operatorInfo);

【问题讨论】:

  • 您确定需要序号吗?试试这个名字。几乎所有 C++ API 都会使用 extern "C" 来表示未损坏的名称。
  • CGSMAdapter 听起来像一个类名,而不是命名空间名。是静态方法吗?
  • 这是 pda 制造商为我们提供的 gsm/gprs 调制解调器适配器的类名,用于拨打电话、发送/接收短信和创建 gprs 连接。

标签: c# compact-framework pinvoke


【解决方案1】:

您只能调用已导出为 C 样式函数的函数。据我所知,您不能通过 P/Invoke 直接调用 C++ 函数,例如:

How to set up a C++ function so that it can be used by p/invoke?

更新

实际上,在通过 P/Invoke 调用函数时,您确实可以使用错误名称。这是我过去永远无法完成的工作,所以我得到了纠正。使用名称而不是序数也应该更有弹性:

参考:Entry Point Not Found Exception

比如:

[DllImport(gsmaAdapterDLLName,
    EntryPoint="?GetCurOperatorInfo@CGSMAdapter@@YAHPAUTagOperatorInfo@@@Z", 
    ExactSpelling = true,
    CallingConvention = CallingConvention.Cdecl)]
public static extern bool GetCurOperatorInfo(out TagOperatorInfo info);

对于 .Net CF:

DllImport(gsmaAdapterDLLName,
    EntryPoint="?GetCurOperatorInfo@CGSMAdapter@@YAHPAUTagOperatorInfo@@@Z", 
    CallingConvention = CallingConvention.WinApi)]
public static extern bool GetCurOperatorInfo(out TagOperatorInfo info);

【讨论】:

  • 它在 declspec(dllexprt) 中导出,如果我做一个垃圾箱,我会得到以下条目:30 1D 000067DC ?GetCurOperatorInfo@CGSMAdapter@@YAHPAUTagOperatorInfo@@@Z
  • @Sorcerer86pt 据我所知,它还必须是 extern "C",因为您不能调用名称混乱的函数。
  • #define DLLGSMADAPTER _declspec(dllexport);;;DLLGSMADAPTER BOOL GetCurOperatorInfo(LPOperatorInfo pInfo);这是函数完整签名
  • 两件事:由于我正在为 .net CF 编程,因此我无法访问 ExactSpelling,并且 CallingConvention 的唯一成员是默认为 SO 调用约定的 WinApi。不过会看看它是否有效,然后会说些什么
  • 如果我们替换调用约定并采用准确的拼写,它就像一个魅力
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多