在C#中使用C ++ DLL应用程序:获取错误“未找到入口点” [英] using C++ DLL in C# windows application:Getting error "Entry point not found"

查看:204
本文介绍了在C#中使用C ++ DLL应用程序:获取错误“未找到入口点”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是在C#中使用C ++库的新手,也是一般的C ++程序设计。我有一个从C ++代码构建的DLL,我相信是一个托管代码,因为DLL的名称是TestManaged.dll。我不是100%确定如果dll / C ++代码是管理/非托管。



我想使用这个DLL的类和方法在我的 C#窗体形成应用程序代码。这个DLL中有多个类。当我在 Object Browser 中的类中调用这些类和方法时,它们都有 Public 标识符。 >

到目前为止,我已经将这个DLL添加到我的C#应用​​程序代码的引用。在我的问题中,我将讨论三个类: Product ReqStatus ProductData 。我可以为这个DLL的各种类创建一个对象,如下所示。

 产品testCall = new ProductClass(); 

此处还有另一个类 ProductData DLL和我可以得到这个类的C ++代码如下。在这种情况下, ProductData 在C#中的 Object Browser 中显示为类,因为它实际上是C ++代码。我不知道这是否重要回答我的问题(在结束)。



以下是一个C ++代码,定义 ProductData struct - ProductData.h 文件。

  #ifdef WIN32_MANAGED 
public ref struct ProductData
#else
struct ProductData
#endif
{
UINT32产品ID; //!产品ID
UINT32 PRoductRev; //!版本号
};下面是一个C ++代码,它定义了 ReqStatus


$ b <枚举 - ReqStatus.h 文件。我在我的C#代码中创建了没有指定标识符的相同枚举。

 枚举ReqStatus 
{
SUCCESS,//!方法成功

//连接错误
NOT_CONNECTED,//!<连接未打开
CONN_TIMEOUT,//!<连接超时,与设备通信
};

现在,我想调用两种方法,并且都有问题:



方法1:是产品中的 getProductData 方法 ProductData 作为参数键入,并返回C $中的枚举类型 ReqStatus 。以下是 gerProductData 方法(如对象浏览器中所示)的声明:

  public ReqStatus getProductData(ProductData data)


$ b b

同样的方法的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 方法类接受一个字符数组(我不知道这个)和一个 ProductData 类型的对象作为参数,并返回 ReqStatus 这是C ++中的枚举类型。以下是 getConnected 方法的声明(如对象浏览器中所示):

  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); //调用getConnected

有一个内部调用 getProductData 方法在 getConnected 方法内。

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

MY C#代码如下,在两个方法调用中都有错误:我在下面的代码片段中将错误放在同一行。两种方法都是独立的。它只是在C ++代码中从 getConnected 方法调用 getProductData 。我想检查,如果我可以单独打电话。

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

ReqStatus status1 = _testProduct.getConnected(COM5,pData); //错误1:最好的重载方法getConnected有一些无效的参数
ReqStatus status2 =(ReqStatus)_testProduct.getProductData(pData); //错误2:由于其保护级别,方法不可访问

对于错误1,各种文章在StackOverflow和其他论坛,但是,无法解决它。只是为了参考,我试图改变SomePortCOM如下,但它没有工作。



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

  String str =COM5 
byte [] bytes = Encoding.ASCII.GetBytes(str);
unsafe
{
固定(字节* p =字节)
{
sbyte * sp =(sbyte *)p;
// SP现在是你想要的
ReqStatus status1 = _testProduct.getConnected(sp,pData);
}
}


$ b $ p

对于Error2,我搜索了很多博客,一个可能的解决方案可能是使用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);

但是,我得到未找到入口点 error。我试图运行dumpbin函数来获取此DLL导出的函数列表。但是,我没有看到任何功能。

  Microsoft(R)COFF / PE Dumper版本10.00.40219.01 
版权所有C)Microsoft Corporation。版权所有。


文件转储C:\Rumit\TestManaged.dll

文件类型:DLL

摘要

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

更新:
此外,我没有看到这个DLL中的任何方法通过Dependency Walker。
现在,我有了C ++的源代码。但我是相当新的C ++编码。



尊敬的,
Rumit

解决方案

  enum ReqStatus 


b $ b

这是你最大的挂断。它声明了一个本机枚举类型,它在托管代码中不可用,并使任何使用它不可访问的代码。您必须使用 enum class 关键字声明其托管版本,如下所示:

  class ReqStatus {
// etc ...
}


I am new to using C++ libraries in C# and also to the C++ programming in general. I have a DLL built from a C++ code which I believe is a 'managed' code as the name of the DLL is "TestManaged.dll". I am not 100% sure if the dll/C++ code is managed/unmanaged.

I want to use classes and methods of this DLL in my C# windows forms application code. There are multiple classes in this DLL. When I chekced these classes and methods inside those classes in Object Browser, all of them have Public identifier.

So far, I have added this DLL to my references of C# application code. There are three classes I would talk about in my question: Product, ReqStatus, ProductData. I could create an object(s) for various classes of this DLL as follows.

Product testCall = new ProductClass();

There is another class called ProductData in this DLL and I could get the C++ code for this class which is as follows. In this case, ProductData is shown as class in Object Browser in C# where as it is actually a struct in C++ code. I am not sure if this is important to answer my question (at the end).

Following is a C++ code that defines ProductData struct - ProductData.h file.

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

Following is a C++ code that defines ReqStatus enum - ReqStatus.h file. I have created the same enum in my C# code with no identifier specified.

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

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

Now, there are two methods I want to call and have problems with both:

Method 1: is a getProductData method inside Product class which accepts object of ProductData type as a parameter and returns the ReqStatus which is an enum type in C++. So following is the declaration of the gerProductData method (as seen in the Object Browser):

public ReqStatus getProductData(ProductData data)

The same method's C++ delcaration is: (The actual method is too long and hence just giving the declaration): This method is inside Prodcut.cpp file

ReqStatus Product::getProductData(ProductData PLATFORM_PTR data)

PLATFORM_PTR is defined as below in Platform.h

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

Method 2: is a getConnected method inside Product class which accepts a character array (I am not sure of this) and an object of ProductData type as a parameter and returns the ReqStatus which is an enum type in C++. So following is the declaration of the getConnected method (as seen in the Object Browser):

public ReqStatus getConnected(sbyte* someChar, ProductData data)

The same method's C++ delcaration is: (The actual method is too long and hence just giving the declaration): This method is inside Prodcut.cpp file

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

C++ code calls the methods as follows:

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

There is an internal call to getProductData method inside the getConnected method.

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

MY C# code is as follows and I got errors at both method calls: I have put errors on the same line in the below code snippet. Both methods are independent. Its just that the getProductData is called from getConnected method in C++ code. I wanted to check if I can call both individually.

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

For Error 1, I tried solutions from various articles on StackOverflow and other forums but, could not solve it. Just for a reference, I tried to change the "SomePortCOM" as follows but it din't work.

UPDATE: This code works fine now and I don't see Error 1(Invalid arguments). Now, I only need to get rid of the Error 2 (Protection level error). Kindly provide any suggestions. Thank you.

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 );
        }
    }

For Error2, I searched so many blogs and found that one of the possible solution could be the use of DLLImport, I tried that as well and I have following issue:

C# declaration of DLLImport:

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

I am calling this function as below from my C# code:

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

However, I am getting Entry point not found error. I tried to run the dumpbin function to get the list of functions exported by this DLL. But, I do not see any functions. Rather just a random output as below.

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

UPDATE: Also, I do not see any methods in this DLL via Dependency Walker. Now, I have got the source code for C++. But I am fairly new to C++ coding. In case any change is required to C++ code, kindly give the directions.

Regards, Rumit

解决方案

 enum ReqStatus

That's your biggest hang-up. That declares a native enum type, it is not usable in managed code and makes any code that uses it inaccessible. You must declare the managed version of it with the enum class keyword, like this:

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

这篇关于在C#中使用C ++ DLL应用程序:获取错误“未找到入口点”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆