未找到DLL的C#命名空间

未找到DLL的C#命名空间,c#,dll,c++-cli,wrapper,C#,Dll,C++ Cli,Wrapper,好的,我会在这篇文章的开头说,在发布这篇文章之前,我在这里做了一个查找并阅读了很多类似的问题和答案 背景信息 使用Visual Studio Professional 2013 目标: 这个项目是我自己的娱乐,并试图学习尽可能多 我有一个名为BialTrut.h的本地C++头文件,它只是一个简单的数据结构,它使用递归逻辑来构建二进制搜索树。它本身运行得很好 我想在C#中构建一个GUI,它使用这个。(它不是真正有用或实用的,我只是选择它,因为我想这么做。此外,虽然二叉树类中的逻辑很复杂(ish),

好的,我会在这篇文章的开头说,在发布这篇文章之前,我在这里做了一个查找并阅读了很多类似的问题和答案

背景信息 使用Visual Studio Professional 2013

目标: 这个项目是我自己的娱乐,并试图学习尽可能多

我有一个名为BialTrut.h的本地C++头文件,它只是一个简单的数据结构,它使用递归逻辑来构建二进制搜索树。它本身运行得很好

我想在C#中构建一个GUI,它使用这个。(它不是真正有用或实用的,我只是选择它,因为我想这么做。此外,虽然二叉树类中的逻辑很复杂(ish),但我只需要调用2个方法,一个addNode方法和一个toString方法,它们返回最大深度和节点数)

我选择使用c++/cli包装器来实现这一点。一切似乎都进行得很顺利,构建成功,并且在我的项目的调试目录中创建了一个.dll文件

现在,我从事情的C端开始。我将.dll文件添加到引用中。然而,当我输入“usingfilename.dll”时,我得到一个错误,说“找不到类型或名称空间…”

重申一下,我做了一些调查。我发现(似乎在VS2010中)不同的目标框架可能会导致此错误。我检查了我的,两者的目标都是net4.5,所以这不是问题所在

下面是我的c++/cli包装器中的代码。也许这与使用模板有关?感谢您的帮助

#pragma once

#include "D:\Schoolwork 2015\Test Projects\CPPtoC#WrapperTest\CPPLogic\CPPLogic\BinaryTree.h"

using namespace System;

namespace BinaryTreeWrapper {

    template<class Data>
    public ref class BinaryTreeWrapperClass
    {
    public:
        BinaryTreeWrapperClass(){ tree = new BinaryTree(); }
        ~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }
        !BinaryTreeWrapperClass(){ delete tree; }

        //methods
        void wrapperAddNode(Data)
        {
            tree->addNode(Data);
        }
        std::string wrapperToString()
        {
            return tree->toString();
        }

    private:
        BinaryTree* tree;
    };
}
#pragma一次
#包括“D:\Schoolwork 2015\Test Projects\CPPtoC\WrapperTest\CPPLogic\CPPLogic\BinaryTree.h”
使用名称空间系统;
命名空间二进制树包装器{
模板
公共引用类BinaryTreeWrapperClass
{
公众:
BinaryTreeWrapperClass(){tree=new BinaryTree();}
~BinaryTreeWrapperClass(){this->!BinaryTreeWrapperClass();}
!BinaryTreeWrapperClass(){删除树;}
//方法
void wrapperAddNode(数据)
{
树->添加节点(数据);
}
std::string wrapperToString()
{
返回树->toString();
}
私人:
二叉树*tree;
};
}
错误的屏幕截图:

编辑 好吧,这里有件奇怪的事。。。我的原始文件使用新代码构建得很好,并生成了一个.dll文件。但是,我决定尝试一个新的项目,因为仍然找不到名称空间。在移动代码并尝试构建时,我遇到了4个错误:

错误1错误C2955:“BinaryTree”:使用类模板需要模板参数列表

错误2错误C2512:“BinaryTree”:没有合适的默认构造函数可用

错误3错误C2662:'void BinaryTree::addNode(Data)':无法将'this'指针从'BinaryTree'转换为'BinaryTree&'

错误4错误C2662:'std::string BinaryTree::toString(void)const':无法将'this'指针从'BinaryTree'转换为'const BinaryTree&'

我完全复制了代码,只是将名称空间更改为“TreeWrapper”,将类名更改为“TreeWrapperClass”

为了提供帮助,我加入了BinaryTree.h文件中的一个片段。还有很多定义“NODE”类的代码,但我不想把它弄得太乱

经过进一步调查,问题似乎出在使用“generic”上。如果我将其全部切换为“template”,它可以正常构建,但不能在C#中用作引用(获取名称空间错误)。我使用非常简单的方法构建了一个测试项目(没有模板)并且能够使用我在C#中制作的.dll包装器。所以问题在于模板和泛型

上次编辑 我发现,如果我更改代码以将模板初始化为“int”,它就可以正常工作,并且我可以在C#中使用它。例如:

...
BinaryTreeWrapperClass(){ tree = new BinaryTree<int>(); }
....
private:
BinaryTree<int>* tree;
。。。
BinaryTreeWrapperClass(){tree=new BinaryTree();}
....
私人:
二叉树*tree;
二叉树

template<class Data>
class BinaryTree
{
private:
    Node<Data>* root;
    unsigned int nNodes;
    unsigned int maxDepth;
    unsigned int currentDepth;
    void traverse(Node<Data>*& node, Data data);
public:
    BinaryTree();
    ~BinaryTree();
    void addNode(Data);
    std::string toString() const 
    {
        std::stringstream sstrm;
        sstrm << "\n\t"
            << "Max Depth:       " << maxDepth << "\n"
            << "Number of Nodes: " << nNodes << "\n";
        return sstrm.str(); // convert the stringstream to a string
    }

};

template<class Data>
BinaryTree<Data>::BinaryTree() //constructor
{
    //this->root = NULL;
    this->root = new Node<Data>();      //we want root to point to a null node.
    maxDepth = 0;
    nNodes = 0;
}

template<class Data>
BinaryTree<Data>::~BinaryTree() //destructor
{

}

template<class Data>
void BinaryTree<Data>::addNode(Data data)
{
    traverse(root, data);   //call traverse to get to the node
    //set currentDepth to 0
    currentDepth = 0;
}

template<class Data>
void BinaryTree<Data>::traverse(Node<Data>*& node, Data data)
{
    //increment current depth
    currentDepth++;

    if (node == NULL)       //adds new node with data
    {
        node = new Node<Data>(data);
        //increment nNode
        nNodes++;
        //increment maxDepth if current depth is greater
        if (maxDepth < currentDepth)
        {
            maxDepth = currentDepth - 1;        //currentDepth counts root as 1, even though its 0;
        }
        return;
    }

    else if (node->getData() >= data)       //case for left, getData must be bigger. The rule is, if a number is equal to getData or greater, it is added to the left node
    {
        Node<Data>* temp = node->getLeftNode();
        traverse(temp, data);               //recursive call, going down left side of tree
        node->setLeftNode(temp);
    }
    else if (node->getData() < data)        //case for right, getData must be less
    {
        Node<Data>* temp = node->getRightNode();
        traverse(temp, data);
        node->setRightNode(temp);
    }
    return;
}
模板
类二叉树
{
私人:
节点*根;
无符号整数n节点;
无符号整数最大深度;
无符号int-currentDepth;
无效导线测量(节点*&节点,数据);
公众:
二叉树();
~BinaryTree();
void addNode(数据);
std::string toString()常量
{
std::stringstream sstrm;
sstrm getData()getRightNode();
导线测量(温度、数据);
节点->设置右侧节点(临时);
}
返回;
}

你声明的是“代码>模板”/Cuth>,但实际上并没有例示它。C++ + CLI模板就像C++模板——如果你不实例化它们,它们就不存在于编译单元之外。

您在这里寻找泛型(是的,C++/CLI既有模板也有泛型)。下面是如何在C++/CLI中声明泛型:

generic<class Data>
public ref class BinaryTreeWrapperClass
{
    // ...
}
这不好,因为您返回的是
std::string
-您不想从C#使用它,所以让我们返回
System::string^
(使用):

请看……这里您必须执行一些真正的互操作。您希望将托管对象传递给本机对象以进行存储。GC将妨碍您

允许GC重新定位任何托管对象(将其移动到另一个内存位置),但您的本机代码对此一无所知。您需要锁定该对象,以便GC不会移动它

有几种方法可以做到这一点,我不知道
BinaryTree::addNode
是什么样子,但我只假设它是
BinaryTree::addNode(void*)

对于长期对象固定,可以使用

完整代码如下所示:

generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
    BinaryTreeWrapperClass()
    {
        tree = new BinaryTree();
        nodeHandles = gcnew System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>();
    }

    ~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }

    !BinaryTreeWrapperClass()
    {
        delete tree;
        for each (auto handle in nodeHandles)
            handle.Free();
    }

    void wrapperAddNode(Data data)
    {
        auto handle = System::Runtime::InteropServices::GCHandle::Alloc(
            safe_cast<System::Object^>(data),
            System::Runtime::InteropServices::GCHandleType::Pinned);
        nodeHandles->Add(handle);
        tree->addNode(handle.AddrOfPinnedObject().ToPointer());
    }

    System::String^ wrapperToString()
    {
        return msclr::interop::marshal_as<System::String^>(tree->toString());
    }

private:
    BinaryTree* tree;
    System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>^ nodeHandles;
};
通用
公共引用类BinaryTreeWrapperClass
{
公众:
BinaryTreeWrapperClass()
{
tree=新的二进制树();
nodeHandles=gcnew System::Collections::Generic::List();
}
~BinaryTreeWrapperClass(){this->!BinaryTreeWrapperClass();}
!BinaryTreeWrapperClass()
{
std::string wrapperToString()
{
    return tree->toString();
}
#include <msclr/marshal_cppstd.h>
System::String^ wrapperToString()
{
    return msclr::interop::marshal_as<System::String^>(tree->toString());
}
void wrapperAddNode(Data)
{
    tree->addNode(Data);
}
generic<class Data>
public ref class BinaryTreeWrapperClass
{
public:
    BinaryTreeWrapperClass()
    {
        tree = new BinaryTree();
        nodeHandles = gcnew System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>();
    }

    ~BinaryTreeWrapperClass(){ this->!BinaryTreeWrapperClass(); }

    !BinaryTreeWrapperClass()
    {
        delete tree;
        for each (auto handle in nodeHandles)
            handle.Free();
    }

    void wrapperAddNode(Data data)
    {
        auto handle = System::Runtime::InteropServices::GCHandle::Alloc(
            safe_cast<System::Object^>(data),
            System::Runtime::InteropServices::GCHandleType::Pinned);
        nodeHandles->Add(handle);
        tree->addNode(handle.AddrOfPinnedObject().ToPointer());
    }

    System::String^ wrapperToString()
    {
        return msclr::interop::marshal_as<System::String^>(tree->toString());
    }

private:
    BinaryTree* tree;
    System::Collections::Generic::List<System::Runtime::InteropServices::GCHandle>^ nodeHandles;
};