Обращение к классу C++ из проекта на C#

  • Автор темы IgMuSh
  • Дата начала
I

IgMuSh

#1
Могу ли я в одном Solution из проекта на C# (основной модуль с оконным интерфейсом) обратиться к классу описанному в дркгом проекте (на C++).
Если да, то как? Я загрузил оба проекта в Solution, сделал reference в первом проекте на второй, пытаюсь создать объект некоего класса, описанного во втором, не ругается.

[codebox]private void frmMain_Load(object sender, EventArgs e)
{
// loading Russian syntax
CCOMSyntaxHolder SyntaxHolder=new CCOMSyntaxHolder() ;


if (!SyntaxHolder.LoadSyntax(morphRussian)) { };
//return -1;

// processing one Russian sentence (from Graphematics to Syntax)
if (!SyntaxHolder.GetSentencesFromSynAn("мама мыла раму", FALSE, FALSE, FALSE)) { };
//return -1;
}[/codebox]


Но когда дальше идёт вызов метода этого класса он пишет:
Error 1 'COMSyntaxHolderNamespace.CCOMSyntaxHolder' does not contain a definition for 'LoadSyntax' C:\Documents and Settings\***\Мои документы\Visual Studio 2005\Projects\WindowsApplication4\WindowsApplication4\frmMain.cs

При этом он почему-то считает, что я обращаюсь к некой структуре с тем же именем что и мой объект, но пустой и считанной откуда то из временного файла(с пометкой from metadata).

Код:
using System;
using System.Runtime.CompilerServices;

namespace COMSyntaxHolderNamespace
{
[CLSCompliant(false)]
[NativeCppClass]
public struct CCOMSyntaxHolder
{
}
}
Что я делаю не так?
 
P

Pasha

#2
IgMuSh
SyntaxHolder.LoadSyntax объявлен как public? Покажи объявление CCOMSyntaxHolder. И используй тэги кода.
 
I

IgMuSh

#3
IgMuSh
SyntaxHolder.LoadSyntax объявлен как public? Покажи объявление CCOMSyntaxHolder. И используй тэги кода.
Вот это у меня в COMSyntaxHolder.h (этот файл во втором проекте):
[codebox]
#ifndef COMSyntaxHolder
#define COMSyntaxHolder

#include "utilit.h"
#include <comdef.h>
#include <atlbase.h>
#import "Lemmatizer.tlb"
#import "MAPost.tlb"
#import "Agramtab.tlb"
#import "Graphan.tlb"
#import "Synan.tlb"


#pragma once

using namespace System;

namespace COMSyntaxHolderNamespace {
public class CCOMSyntaxHolder
{
public:
MorphLanguageEnum m_CurrentLanguage;

GRAPHANLib::IGraphmatFilePtr m_piGraphan;
LEMMATIZERLib::ILemmatizerPtr m_piLemmatizer;
AGRAMTABLib::IGramTabPtr m_pGramTab;
MAPOSTLib::IMAPostPtr m_piMAPost;
SYNANLib::ISentencesCollectionPtr m_piSentCollection;
LEMMATIZERLib::IPLMLineCollectionPtr m_piAfterMorphPlmLines;
LEMMATIZERLib::IPLMLineCollectionPtr m_piBeforeSyntaxPlmLines;

CCOMSyntaxHolder();
~CCOMSyntaxHolder();
BOOL LoadSyntax(MorphLanguageEnum langua);

void DeleteProcessors();
BOOL LoadSyntaxModule(MorphLanguageEnum langua);

BOOL BuildBeforeSyntax(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults);
BOOL BuildSyntax(BOOL bSaveIntermResults);
BOOL GetSentencesFromSynAn(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults);



};
extern string GetClauseTypeDescr(MorphLanguageEnum Language, const SYNANLib::IClausePtr& piClause, int ClauseRootNo);
#endif
}[/codebox]
 
I

IgMuSh

#6
Pasha
Спасибо!
Класс действительно стал доступен, но почему-то не все методы(?!)

Вот этот участок даёт ошибку:

[codebox]using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using COMSyntaxHolderNamespace;
namespace TestSynAn
{
public partial class frmMain : Form
{
public frmMain()
{
InitializeComponent();
}

private void frmMain_Load(object sender, EventArgs e)
{
// loading Russian syntax
CCOMSyntaxHolder SyntaxHolder=new CCOMSyntaxHolder();


if (!SyntaxHolder.LoadSyntax(morphRussian)) { };
//return -1;

// processing one Russian sentence (from Graphematics to Syntax)
if (!SyntaxHolder.GetSentencesFromSynAn("мама мыла раму", FALSE, FALSE, FALSE)) { };
//return -1;
}
}
}[/codebox]


Вызов LoadSyntax проходит, а на вызов GetSentencesFromSynAn ругается вот так:

[codebox]Error 2 The name 'FALSE' does not exist in the current context C:\Documents and Settings\****\Мои документы\Visual Studio 2005\Projects\WindowsApplication4\WindowsApplication4\frmMain.cs 28
Error 3 The name 'FALSE' does not exist in the current context C:\Documents and Settings\****\Мои документы\Visual Studio 2005\Projects\WindowsApplication4\WindowsApplication4\frmMain.cs 28
Error 4 The name 'FALSE' does not exist in the current context C:\Documents and Settings\****\Мои документы\Visual Studio 2005\Projects\WindowsApplication4\WindowsApplication4\frmMain.cs 28
Error 1 The name 'morphRussian' does not exist in the current context C:\Documents and Settings\****\Мои документы\Visual Studio 2005\Projects\WindowsApplication4\WindowsApplication4\frmMain.cs 24[/codebox]


Причём опять если спросить у VS оределение класса CCOMSyntaxHolder, то он показывает файл "CCOMSyntaxHolder [from metadata]":

[codebox]using System;

namespace COMSyntaxHolderNamespace
{
public class CCOMSyntaxHolder : IDisposable
{
public MorphLanguageEnum m_CurrentLanguage;

public CCOMSyntaxHolder();

public int BuildSyntax(int bSaveIntermResults);
public void DeleteProcessors();
public override sealed void Dispose();
protected virtual void Dispose(bool __p1);
public int LoadSyntax(MorphLanguageEnum langua);
public int LoadSyntaxModule(MorphLanguageEnum langua);
}
}[/codebox]


На самом же деле класс описан вот так:

"COMSyntaxHolder.h"
[codebox]#ifndef COMSyntaxHolder
#define COMSyntaxHolder

#include "utilit.h"
#include <comdef.h>
#include <atlbase.h>
#import "Lemmatizer.tlb"
#import "MAPost.tlb"
#import "Agramtab.tlb"
#import "Graphan.tlb"
#import "Synan.tlb"


#pragma once

using namespace System;

namespace COMSyntaxHolderNamespace {
public ref class CCOMSyntaxHolder
{
public:
MorphLanguageEnum m_CurrentLanguage;

GRAPHANLib::IGraphmatFilePtr* m_piGraphan;
LEMMATIZERLib::ILemmatizerPtr* m_piLemmatizer;
AGRAMTABLib::IGramTabPtr* m_pGramTab;
MAPOSTLib::IMAPostPtr* m_piMAPost;
SYNANLib::ISentencesCollectionPtr* m_piSentCollection;
LEMMATIZERLib::IPLMLineCollectionPtr* m_piAfterMorphPlmLines;
LEMMATIZERLib::IPLMLineCollectionPtr* m_piBeforeSyntaxPlmLines;

CCOMSyntaxHolder();
~CCOMSyntaxHolder();

BOOL LoadSyntax(MorphLanguageEnum langua);
BOOL BuildBeforeSyntax(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults);
void DeleteProcessors();
BOOL LoadSyntaxModule(MorphLanguageEnum langua);
BOOL BuildSyntax(BOOL bSaveIntermResults);
BOOL GetSentencesFromSynAn(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults);



};
extern string GetClauseTypeDescr(MorphLanguageEnum Language, const SYNANLib::IClausePtr& piClause, int ClauseRootNo);
#endif
}[/codebox]


"COMSyntaxHolder.cpp"
[codebox]#include "stdafx.h"

#include "COMSyntaxHolder.h"


#define COM_TRY try {
#define COM_CATCH(msg) } catch(...) { ErrorMessage(msg); return FALSE; }

COMSyntaxHolderNamespace::CCOMSyntaxHolder::CCOMSyntaxHolder()
{
};

COMSyntaxHolderNamespace::CCOMSyntaxHolder::~CCOMSyntaxHolder()
{
DeleteProcessors();
};
BOOL COMSyntaxHolderNamespace::CCOMSyntaxHolder::GetSentencesFromSynAn(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults)
{
if (!BuildBeforeSyntax(str, bFile, bWriteIntermFiles, bSaveIntermResults))
return FALSE;

return BuildSyntax(bSaveIntermResults);
};

BOOL COMSyntaxHolderNamespace::CCOMSyntaxHolder::LoadSyntaxModule(MorphLanguageEnum langua)
{
try
{
m_piSentCollection = 0;
HRESULT hr = m_piSentCollection->CreateInstance(__uuidof(SYNANLib::SentencesCollection));
if( FAILED(hr) )
{
ErrorMessage("SynAn has crushed, maybe \"SynAn.dll\" is not registered.");
return FALSE;
}


m_piSentCollection->GetInterfacePtr()->PutSyntaxLanguage(langua);
m_piSentCollection->GetInterfacePtr()->SetLemmatizer(m_piLemmatizer->GetInterfacePtr());


if (langua != morphRussian)
{
m_piSentCollection->GetInterfacePtr()->PutEnableThesauri( FALSE);
};

m_piSentCollection->GetInterfacePtr()->PutKillHomonymsMode(CoverageKillHomonyms);


hr = m_piSentCollection->GetInterfacePtr()->InitializeProcesser();
if( FAILED(hr) )
{
ErrorMessage("Can not load syntax dictionaries.");
return FALSE;
}

}
catch(...)
{
ErrorMessage("SynAn has crushed, maybe \"SynAn.dll\" is not registered.");
return FALSE;
}
return TRUE;
};

BOOL COMSyntaxHolderNamespace::CCOMSyntaxHolder::LoadSyntax(MorphLanguageEnum langua)
{
HRESULT hr;
try
{
m_piGraphan = 0;
m_piGraphan->CreateInstance(__uuidof(GRAPHANLib::GraphmatFile));
m_piGraphan->GetInterfacePtr()->PutLanguage(langua);
m_piGraphan->GetInterfacePtr()->LoadDicts();

m_piLemmatizer = 0;
if (langua == morphRussian)
hr = m_piLemmatizer->CreateInstance(__uuidof(LEMMATIZERLib::LemmatizerRussian));
else
if (langua == morphGerman)
hr = m_piLemmatizer->CreateInstance(__uuidof(LEMMATIZERLib::LemmatizerGerman));
else
if (langua == morphEnglish)
hr = m_piLemmatizer->CreateInstance(__uuidof(LEMMATIZERLib::LemmatizerEnglish));
if( FAILED(hr) )
{
ErrorMessage("CCOMSyntaxHolder", "MorphAn has crushed, maybe \"lemmatizer.dll\" is not registered.");
return FALSE;
}


hr = m_piLemmatizer->GetInterfacePtr()->LoadDictionariesRegistry();
if( FAILED(hr) )
{
ErrorMessage("Can not load morphology dictionaries.");
return FALSE;
}

m_pGramTab = 0;
if (langua == morphRussian)
hr = m_pGramTab->CreateInstance(__uuidof(AGRAMTABLib::RusGramTab));
else
if (langua == morphGerman)
hr = m_pGramTab->CreateInstance(__uuidof(AGRAMTABLib::GerGramTab));
else
if (langua == morphEnglish)
hr = m_pGramTab->CreateInstance(__uuidof(AGRAMTABLib::EngGramTab));

if( FAILED(hr) )
{
ErrorMessage("MorphAn has crushed, maybe \"agramtab.dll\" is not registered.");
return FALSE;
}

hr = m_pGramTab->GetInterfacePtr()->Load();
if( FAILED(hr) )
{
ErrorMessage("Can not load rusgramtab .");
return FALSE;
}

}
catch(...)
{
ErrorMessage("MorphAn has crushed, maybe \"lemmatizer.dll\" is not registered.");
return FALSE;
}

try
{
m_piAfterMorphPlmLines = 0;
m_piBeforeSyntaxPlmLines = 0;

if( FAILED( m_piMAPost->CreateInstance(__uuidof(MAPOSTLib::MAPost)) ) )
ErrorMessage("Mapost has crushed, maybe \"Mapost.dll\" is not registered.");

if (langua != morphEnglish)
m_piMAPost->GetInterfacePtr()->Init(langua, m_piLemmatizer->GetInterfacePtr() , m_pGramTab->GetInterfacePtr() );

}
catch(...)
{
ErrorMessage("Postmorphology has crushed, maybe \"MApost.dll\" is not registered.");
return FALSE;
}


if (!LoadSyntaxModule(langua))
return FALSE;

m_CurrentLanguage = langua;

return TRUE;
};

BOOL COMSyntaxHolderNamespace::CCOMSyntaxHolder::BuildBeforeSyntax(string str, BOOL bFile, BOOL bWriteIntermFiles, BOOL bSaveIntermResults)
{
m_piBeforeSyntaxPlmLines = 0;
m_piAfterMorphPlmLines = 0;
HRESULT hr = m_piAfterMorphPlmLines->CreateInstance(__uuidof(LEMMATIZERLib::pLMLineCollection));
m_piAfterMorphPlmLines->GetInterfacePtr()->AttachLemmatizer(m_piLemmatizer->GetInterfacePtr() );

m_piSentCollection->GetInterfacePtr()->ClearSentences();
string log_path;
string FileName = "rossdev.log";
try {

log_path = GetRegistryString( "Software\\Dialing\\Logs\\Main" );
log_path += "/";
}
catch (...) {
};
if (bFile)
if (!FileExists(str.c_str()))
{
ErrorMessage (Format("file %s is not found", str.c_str()));
return FALSE;
};


COM_TRY


if( bFile )
m_piGraphan->GetInterfacePtr()->LoadFileToGraphan(_bstr_t(str.c_str()).copy());
else
m_piGraphan->GetInterfacePtr()->LoadStringToGraphan(_bstr_t(str.c_str()).copy());




COM_CATCH( "GraphAn has crushed.");




COM_TRY
m_piAfterMorphPlmLines->GetInterfacePtr()->ProcessHyphenWords(m_piGraphan->GetInterfacePtr() );


m_piAfterMorphPlmLines->GetInterfacePtr()->ProcessPlmLines(m_piGraphan->GetInterfacePtr() );
if (bWriteIntermFiles)
m_piAfterMorphPlmLines->GetInterfacePtr()->SaveToFile(string(log_path+"before.lem").c_str());

if (!bSaveIntermResults)
m_piGraphan->GetInterfacePtr()->FreeTable();


COM_CATCH( "MorphAn has crushed.");

COM_TRY
if (m_CurrentLanguage == morphEnglish)
{
m_piBeforeSyntaxPlmLines = 0;
m_piBeforeSyntaxPlmLines->CreateInstance(__uuidof(LEMMATIZERLib::pLMLineCollection));
m_piBeforeSyntaxPlmLines->GetInterfacePtr()->AttachLemmatizer(m_piLemmatizer->GetInterfacePtr() );
m_piBeforeSyntaxPlmLines->GetInterfacePtr()->CopyItems(m_piAfterMorphPlmLines->GetInterfacePtr());
}
else
//m_piMAPost->GetInterfacePtr()->ProcessData(m_piAfterMorphPlmLines->GetInterfacePtr()).QueryInterface(__uuidof(LEMMATIZERLib::pLMLineCollection),
m_piBeforeSyntaxPlmLines) ;
if (bWriteIntermFiles)
m_piBeforeSyntaxPlmLines->GetInterfacePtr()->SaveToFile(string(log_path+"after.lem").c_str());

COM_CATCH( "PostMorphology has crushed.");

if (!bSaveIntermResults)
m_piAfterMorphPlmLines->GetInterfacePtr()->Clear();

return TRUE;
};

BOOL COMSyntaxHolderNamespace::CCOMSyntaxHolder::BuildSyntax(BOOL bSaveIntermResults)
{
COM_TRY

assert( !(m_piSentCollection == NULL) );
HRESULT hr = m_piSentCollection->GetInterfacePtr()->raw_ProcessData(m_piBeforeSyntaxPlmLines->GetInterfacePtr() );
if( FAILED(hr) )
{
m_piBeforeSyntaxPlmLines = 0;
ErrorMessage("SynAn has crushed.");
return FALSE;
}

if (!bSaveIntermResults)
m_piBeforeSyntaxPlmLines->GetInterfacePtr()->Clear();



COM_CATCH( "SynAn has crushed.")

return TRUE;
};



void COMSyntaxHolderNamespace::CCOMSyntaxHolder::DeleteProcessors()
{
m_piLemmatizer = NULL;
m_pGramTab = NULL;
m_piSentCollection = NULL;
m_piGraphan = 0;
m_piAfterMorphPlmLines = 0;
m_piBeforeSyntaxPlmLines = 0;
m_piMAPost = 0;
};


string COMSyntaxHolderNamespace::GetClauseTypeDescr(MorphLanguageEnum Language, const SYNANLib::IClausePtr& piClause, int ClauseRootNo)
{
if (ClauseRootNo == -1)
{
if (Language == morphRussian)
return "ПУСТЫХА";
else
return "EMPTY";
}
else
{
return (const char*)piClause->ClauseRoots[ClauseRootNo]->GetDescription();
}
};[/codebox]

Не пойму в чём дело...какая разница между LoadSyntax и GetSentencesFromSynAn? :wacko:
 
A

alexsid

#7
Надо переопределить FALSE и morphRussian

Это разные методы.

ИМХО вообще определять класс C++ как managed было не надо. Надо было оставить его как есть.
И просто зарегистрировать COM объект в системе и сделать на него референс из С#.