【问题标题】:PInvoke with a "strange" functionPInvoke 使用“奇怪”功能
【发布时间】:2009-11-18 04:04:29
【问题描述】:

我有一个用 C++ 编写的 .dll,其函数定义如下:

EDK_API int EE_CognitivSetCurrentLevel  ( unsigned int  userId,  
  EE_CognitivLevel_t  level,  
  EE_CognitivAction_t  level1Action,  
  EE_CognitivAction_t  level2Action,  
  EE_CognitivAction_t  level3Action,  
  EE_CognitivAction_t  level4Action   
)    

Set the current Cognitiv level and corresponding action types. 


Parameters:
userId  - user ID  
level  - current level (min: 1, max: 4)  
level1Action  - action type in level 1  
level2Action  - action type in level 2  
level3Action  - action type in level 3  
level4Action  - action type in level 4 

这个函数的用法,如上图所示:如果level = 1,会这样调用:

EE_CognitivSetCurrentLevel(userId,1,level1Action);

如果级别 = 2,则:

EE_CognitivSetCurrentLevel(userId,2,level1Action,level2Action);

等等……

如何在 C# 中调用此函数?

非常感谢!

【问题讨论】:

  • C++ EE_CognitivSetCurrentLevel() 函数是使用默认参数编写的,还是采用可变数量参数的 __cdecl 函数?正确的做法会有所不同。
  • 很遗憾我没有这个dll的原始源代码。我怎么知道它是使用默认参数编写的还是 _cdecl 函数?
  • 如果默认不使用相同的约定,你会得到错误的参数。如果您想明确设置它,请将其添加到我的答案中的 DllImport 参数中:CallingConvention=CallingConvention.Cdecl。如果需要,请查看 msdn.microsoft.com/en-us/library/… 了解其他选项。

标签: c# c++ pinvoke


【解决方案1】:

假设EE_CognitivLevel_tEE_CognitivAction_t 是整数:

[DllImport ("yourdll", EntryPoint ("EE_CognitivSetCurrentLevel")]
extern static int EE_CognitivSetCurrentLevel1 (int level, int level1);

[DllImport ("yourdll", EntryPoint ("EE_CognitivSetCurrentLevel")]
extern static int EE_CognitivSetCurrentLevel2 (int level, int level1, int level2);

等等...哦,并确保该函数位于 extern "C" {} 中,以便 C++ 编译器不会破坏名称。

【讨论】:

    【解决方案2】:

    因为它是一个 C++ 函数,我假设它有 default parameters. 当你用太少的参数调用函数时,C++ 编译器会自动用默认值填充缺失的参数。 C# 不支持默认参数,也不支持从 DLL 调用。如果是这种情况,那么您需要找出这些默认参数是什么并手动传递它们。如果您将错误数量的参数传递给函数,您最终会出现奇怪的行为(或者它可以工作,谁知道)。

    您可以在 C# 中使用重载来提供您在 C++ 中看到的相同行为:

    class EEFunctions {
        [DllImport ("yourdll", EntryPoint ("EE_CognitivSetCurrentLevel")]
        private extern static int EE_CognitivSetCurrentLevelDLL(int level, int level1,
            int level2, int level3, int level4);
    
        private int defaultLevel = 0;  // This is just an example
    
        public static int EE_CognitivSetCurrentLevel(int level, int level1) {
            return EE_CognitivSetCurrentLevel(level, level1, 
                 defaultLevel, defaultLevel, defaultLevel);
        }
    
        public static int EE_CognitivSetCurrentLevel(int level, int level1, int level2) {
            return EE_CognitivSetCurrentLevel(level, level1, 
                 level2, defaultLevel, defaultLevel);
        }
    
        public static int EE_CognitivSetCurrentLevel(int level, int level1,
             int level2, int level3) {
            return EE_CognitivSetCurrentLevel(level, level1, 
                 level2, level3, defaultLevel);
        }
    
        public static int EE_CognitivSetCurrentLevel(int level, int level1,
             int level2, int level3, int level4) {
            return EE_CognitivSetCurrentLevel(level, level1, 
                 level2, level3, level4);
        }
    }
    

    这也假设所有参数都是整数。如果您可以在 C++ 标头中找到参数类型的定义,则可以在 C# 中创建兼容的类型。

    【讨论】:

      猜你喜欢
      • 2014-07-29
      • 2021-05-20
      • 2015-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-18
      • 1970-01-01
      相关资源
      最近更新 更多