首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C++ CLI错误C3767:不可访问的候选函数

C++ CLI错误C3767:不可访问的候选函数
EN

Stack Overflow用户
提问于 2009-06-03 20:59:08
回答 3查看 19.1K关注 0票数 16

我是C++ CLI的新手,来自非托管的C++世界。

我得到了一个错误:

代码语言:javascript
复制
candidate function(s) not accessible 

当我传递一个std::string作为方法参数的一部分时。

以下是确切的代码:

Lib项目(编译为.dll项目)

//Lib.h

代码语言:javascript
复制
#pragma once

public ref class Lib
{
public:
  Lib(void);

public:
  void Extract( std::string& data_ );
};

//Lib.cpp

代码语言:javascript
复制
#include "Lib.h"

Lib::Lib(void)
{
}

void Lib::Extract( std::string& data_ )
{
  data_.empty();
}

LibTest项目(编译为application.exe)

// LibTest.h

代码语言:javascript
复制
#pragma once

ref class LibTest
{
public:
  LibTest(void);
};

// LibTest.cpp

代码语言:javascript
复制
#include "LibTest.h"

LibTest::LibTest(void)
{
  Lib^ lib = gcnew Lib;
  lib->Extract( std::string("test") );
}

int main()
{
  return 0;
}

编译器错误:

代码语言:javascript
复制
1>------ Build started: Project: LibTest, Configuration: Debug Win32 ------
1>Compiling...
1>LibTest.cpp
1>.\LibTest.cpp(7) : error C3767: 'Lib::Extract': candidate function(s) not accessible
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-06-03 23:22:28

问题是std::string将作为内部(非公共)类型进行编译。这实际上是VS 2005+中的一个更改:

http://msdn.microsoft.com/en-us/library/ms177253(VS.80).aspx

默认情况下,本机类型在程序集之外是私有的,默认情况下,本机类型在程序集之外是不可见的。有关程序集外部类型可见性的详细信息,请参阅类型可见性。这一变化主要是由开发人员在引用VisualC++编写的元数据时使用其他不区分大小写的语言的需求驱动的。

您可以使用Ildasm或反射器确认这一点,您将看到您的提取方法编译为:

代码语言:javascript
复制
public unsafe void Extract(basic_string<char,std::char_traits<char>,std::allocator<char> >* modopt(IsImplicitlyDereferenced) data_)

将basic_string编译为:

代码语言:javascript
复制
[StructLayout(LayoutKind.Sequential, Size=0x20), NativeCppClass, MiscellaneousBits(0x40), DebugInfoInPDB, UnsafeValueType]
internal struct basic_string<char,std::char_traits<char>,std::allocator<char> >

注意内部。

不幸的是,您随后无法从不同的程序集调用这样的方法。

在某些情况下,有一个解决办法:可以强制使用make_public杂注将本机类型编译为public。

例如,如果您有一个方法Extract2,例如:

代码语言:javascript
复制
void Extract2( std::exception& data_ );

您可以强制将std::exception编译为public,方法是预先包含以下语用语句:

代码语言:javascript
复制
#pragma make_public(std::exception)

此方法现在可跨程序集调用。

不幸的是,make_public不适用于模板化的类型(std::string只是basic_string<>的类型),我不认为您可以做任何事情来使它工作。我建议在所有公共API中使用托管类型System::String^。这还确保您的库可以轻松地从其他CLR语言(如c# )调用。

票数 27
EN

Stack Overflow用户

发布于 2013-08-19 11:29:38

如果您只需访问internal方法,那么另一项工作将是将项目作为朋友大会进行如下操作:

//Lib项目

代码语言:javascript
复制
#pragma once

//define LibTest as friend assembly which will allow access to internal members
using namespace System;
using namespace System::Runtime::CompilerServices;
[assembly:InternalsVisibleTo("LibTest")];

public ref class Lib
{
 public:
  Lib(void);

 public:
  void Extract( std::string& data_ );
};

//LibTest项目

代码语言:javascript
复制
#pragma once

#using <Lib.dll> as_friend

ref class LibTest
{
  public:
    LibTest(void);
};
票数 4
EN

Stack Overflow用户

发布于 2014-06-18 12:25:56

除了上述解决方案外,还可以对模板类型进行子类处理以获得非模板类型,并将其定义包含在两个项目中,从而克服了上述一些问题。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/947213

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档