使用C ++ DLL在C#Windows应用程序:获得错误“入口点找不到”(using C++ DL

2019-10-17 20:49发布

我是新来的C#和也是在一般的C ++程序使用C ++库。 我从C ++代码,我相信这是一个“托管”代码为DLL的名称是“TestManaged.dll”建立了一个DLL。 我不是100%肯定,如果DLL / C ++代码托管/非托管。

我想用类和这个DLL的方法在我的C# windows forms application代码。 有多个类在此DLL。 当我在chekced这些类中,这些类和方法Object Browser ,他们都有Public标识。

到目前为止,我已经加入这个DLL我的C#应用​​程序代码引用。 有三类我会在我的问题谈: ProductReqStatusProductData 。 我可以创建关于各种类此DLL如下的一个对象(或多个)。

Product testCall = new ProductClass();

还有一种叫类ProductData在此DLL中,我能得到C ++代码,这个类如下。 在这种情况下, ProductData被示为类Object Browser在C#作为在那里它实际上是在C ++代码一个结构。 我不知道是否回答我的问题(在末尾),这是非常重要的。

下面是一个C ++代码定义ProductData结构- ProductData.h文件。

#ifdef WIN32_MANAGED 
public ref  struct ProductData
#else
struct ProductData
#endif
{
    UINT32 ProductId;           //!< Product ID    
    UINT32 PRoductRev;         //!< Build Revision
};

下面是一个C ++代码定义ReqStatus枚举- ReqStatus.h文件。 我有没有指定的标识符创建的同一个枚举在我的C#代码。

enum ReqStatus
{
    SUCCESS,            //!< Method was successful

    //Connection errors
    NOT_CONNECTED,      //!< Connection not open 
    CONN_TIMEOUT,       //!< Connection timed out commuincating with device
};

现在,有两种方法我想打个电话有两个问题:

方法1:是一个getProductData内部方法Product类,它接受的对象ProductData类型作为参数并返回ReqStatus这是在C ++枚举类型。 所以以下是声明gerProductData方法(如见于Object Browser ):

public ReqStatus getProductData(ProductData data)

同样的方法的C ++ delcaration是:(实际的方法是太长,因此只是给报关):此方法是内部Prodcut.cpp文件

ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)

PLATFORM_PTR被定义为下面Platform.h

#ifdef WIN32_MANAGED
#define PLATFORM_PTR ^
#else
#define PLATFORM_PTR *
#endif

方法2:是一个getConnected内部方法Product类,它接受的字符阵列(我不知道这个问题)和的目的ProductData类型作为参数并返回ReqStatus这是在C ++枚举类型。 所以以下是声明getConnected方法(如见于Object Browser ):

public ReqStatus getConnected(sbyte* someChar, ProductData data)

同样的方法的C ++ delcaration是:(实际的方法是太长,因此只是给报关):此方法是内部Prodcut.cpp文件

ReqStatus Product::getConnected(const char *someChar, ProductData PLATFORM_PTR data)

C ++代码调用方法如下:

private : Product^  _testProduct;
testProduct = gcnew Product();
ProductData ^ data = gcnew ProductData();

int portNum = Decimal::ToInt16(7); 
char portName[32];
_snprintf(&portName[0], sizeof(portName),"COM%d", portNum);
ReqStatus status = _testProduct->getConnected(&portName[0], data); //Calling getConnected

还有就是内部通话getProductData里面方法getConnected方法。

ReqStatus status = getProductData(data); //data is the same which was passed to the getConnected method

我的C#代码如下,我在这两个方法调用了错误:我已经把错误在下面的代码片段在同一行。 这两种方法是独立的。 它只是在getProductData从所谓getConnected在C ++代码的方法。 我想检查我是否可以单独通话双方。

ProductData pData = new ProductData(); // OK
Product _testProduct = new Product();  // OK

ReqStatus status1 = _testProduct.getConnected("COM5", pData ); //Error 1: The best overloaded method getConnected has some invalid arguments
ReqStatus status2 = (ReqStatus)_testProduct.getProductData(pData ); // Error 2: Method is inaccessible due to its protection level

对于错误1,我试图从StackOverflow上和其他论坛,但各种物品的解决方案,解决不了它。 只是一个参考,我试图改变“SomePortCOM”如下,但它din't工作。

更新此代码工作正常,现在我没有看到错误1(无效参数)。 现在,我只需要摆脱错误2(防护等级误差)。 请提供任何建议。 谢谢。

String str = "COM5";
byte[] bytes = Encoding.ASCII.GetBytes(str);
unsafe
    {
        fixed (byte* p = bytes)
        {
                sbyte* sp = (sbyte*)p;
                //SP is now what you want
                   ReqStatus status1 = _testProduct.getConnected(sp, pData );
        }
    }

对于误差2,我搜索了这么多的博客,发现可能的解决方案之一可能是使用的DllImport的,我想,也和我有以下问题:

dllimport的C#的声明:

[DllImport("TestManaged.dll",EntryPoint="getConnected")]
        public static extern ReqStatus getConnected(String SerialPort, ref ProductData pData);

我从我的C#代码如下调用此函数:

ProductData pData = new ProductData();
String str = "COM7";
ReqStatus status1 = getConnected(str, ref pData);

但是,我越来越Entry point not found错误。 我试图运行DUMPBIN函数来获取这个DLL导出的函数列表。 但是,我没有看到任何功能。 更确切地说只是一个随机的输出如下。

Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\Rumit\TestManaged.dll

File Type: DLL

  Summary

        2000 .data
       22000 .rdata
        1000 .reloc
        1000 .rsrc
       13000 .text

更新:另外,我没有看到通过Dependency Walker中该DLL的任何方法。 现在,我已经得到了C ++源代码。 但我是相当新的C ++编码。 在任何情况下,需要改变到C ++代码,请给方向。

问候,Rumit

Answer 1:

 enum ReqStatus

这是你最大的挂断。 声明本地枚举类型,它不是在托管代码中使用,并使得使用它无法访问任何代码。 您必须声明它与枚举类的关键字,这样的托管版本:

public enum class ReqStatus {
    // etc...
}


Answer 2:

在你的代码的不安全块将使它所以你的组件不能被用于安全协议验证,所以要警惕这一点。 当我叫从C ++从C#方法(本地或不)我不得不使用的PInvoke(平台调用)给他们打电话。 对于一个保护级别,我知道你说的一切都在C ++公众,但如果你是新来的C ++,你可能已经做了一个快速的语法错误。 在C#中,所有的方法都需要通过存储说明符的前面(公共,保护,等...),但在C ++中,你将存储符其次是存储和下宣布存储之间的冒号,一切都将是存储类型。 也许这是你的问题?



Answer 3:

谢谢汉斯,对指出的问题。 只是,我做了枚举定义为“公共”。 但是,我不知道,如果你把“阶级”错误,抑或是故意的,因为它是给我这么多的错误,因为它并没有把它作为一个枚举和我用枚举每一个地方问的对象。 让我知道如果我在这里误解的话。

所以,我把它通过使枚举公众只是工作。 但是,我仍然无法找到如何正确的价值观传递到从C#的C ++函数。 (ERROR1在原来的职位)。

当我debuged C ++代码,它通过“0x0034E808‘COM5’值(I假设它是一个存储器位置和值?)对的第一个参数getConnected方法。我试图通过实现不安全的方法传递该值(说明在我原来的职位的错误1),它通过“0x0277aab8”(又似乎有些内存地址),但却无法连接到它(获得串口超时错误)。我是不是不正确地传递相比,C ++方法的价值?

问候,Rumit



文章来源: using C++ DLL in C# windows application:Getting error “Entry point not found”