C ++ CLI错误C3767:无法访问候选函数

时间:2009-06-03 20:59:08

标签: c++-cli

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

我收到了这个错误:

candidate function(s) not accessible 

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

以下是确切的代码:

Lib Project(编译为.dll项目)

// Lib.h

#pragma once

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

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

// Lib.cpp

#include "Lib.h"

Lib::Lib(void)
{
}

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

LibTest项目(编译为application.exe)

// LibTest.h

#pragma once

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

// LibTest.cpp

#include "LibTest.h"

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

int main()
{
  return 0;
}

编译错误:

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

3 个答案:

答案 0 :(得分:25)

问题是std :: string将编译为内部(非公共)类型。这实际上是VS 2005 +的变化:

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

默认情况下,本机类型在程序集外部是私有的 默认情况下,现在在组件外部不会显示本机类型。有关程序集外部类型可见性的更多信息,请参阅类型可见性。在引用Visual C ++中创建的元数据时,此更改主要是由使用其他不区分大小写的语言的开发人员的需求驱动的。

您可以使用Ildasm或reflector进行确认,您将看到您的提取方法编译为:

public unsafe void Extract(basic_string<char,std::char_traits<char>,std::allocator<char> >* modopt(IsImplicitlyDereferenced) data_)

将basic_string编译为:

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

请注意内部

不幸的是,您无法从其他程序集中调用此类方法。

在某些情况下有一种解决方法:您可以使用make_public pragma强制将本机类型编译为公共类型。

e.g。如果你有一个方法Extract2,如:

void Extract2( std::exception& data_ );

您可以通过事先包含此pragma语句来强制将std :: exception编译为public:

#pragma make_public(std::exception)

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

不幸的是,make_public对模板化类型不起作用(std :: string只是basic_string&lt;&gt;的typedef) 我认为你无法做任何事情让它发挥作用。我建议在所有公共API中使用托管类型System :: String ^。这也确保您的库可以从其他CLR语言(如c#

)轻松调用

答案 1 :(得分:4)

如果您只是必须访问internal方法,则另一种方法是将项目设为Friend Assemblies,如下所示:

// Lib Project

#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 Project

#pragma once

#using <Lib.dll> as_friend

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

答案 2 :(得分:2)

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