Your privacy
By clicking “Accept all cookies”, you agree Stack Exchange can store cookies on your device and disclose information in accordance with our Cookie Policy.
otreblA_SNAKE_[ITA]
Hi there guys,
I’m studying C++ with Deitel «C++ How To Program» and I’ve done a small «gradebook» program. However I’ve a problem: when I try tu build&run my program I’ve an error:
C:UsersAlbertoAppDataLocalTempccSdybij.o:main.cpp|| multiple definition of `main’|
objDebugmain.o:C:UsersAlbertoDocumentsProgetti C++ CodeBlocksConsoleApplication24main.cpp|10|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|
Here’s my simple program:
gradebook.h
#include <string>
using std::string;class GradeBook
{
public:
GradeBook( string );
void setCourseName( string );
string getCourseName();
void displayMessage();
private:
string courseName;
};
gradebook.cpp
#include <iostream>
using std::cout;
using std::endl;#include "GradeBook.h"
GradeBook::GradeBook( string name )
{
setCourseName( name );
}
void GradeBook::setCourseName( string name )
{
if ( name.length() <= 25 )
courseName = name;
if ( name.length() > 25 )
{
courseName = name.substr( 0, 25 );
cout << "Name "" << name << "" exceeds maximum lenght (25).n" << "Limiting courseName to first 25 characters.n" << endl;
}
}
string GradeBook::getCourseName()
{
return courseName;
}
void GradeBook::displayMessage()
{
cout << "Welcome to the GradeBook forn" << getCourseName() << "!" << endl;
}
Main.cpp
#include <iostream>
using std::cout;
using std::endl;#include "GradeBook.h"
int main()
{
//creazione di due oggetti GradeBook
GradeBook gradeBook1( "CS101 Introduction to C++ Programming" );
GradeBook gradeBook2( "CS102 Data Structures in C++" );
cout << "gradeBook1's initial name is: " << gradeBook1.getCourseName() << "ngradeBook2's initial name is: " << gradeBook2.getCourseName() << endl;
gradeBook1.setCourseName( "CS101 C++ Programming" );
cout << "ngradeBook1's course name is: " << gradeBook1.getCourseName() << "ngradeBook2's course name is: " << gradeBook2.getCourseName() << endl;
return 0;
}
In my «Linker Settings» I’ve included both gradebook.h and gradebook.cpp files but that doesn’t help
Thank you,
otreblA
« Last Edit: June 23, 2010, 11:40:07 am by otreblA_SNAKE_[ITA] »
Logged
Undisputed, ну тогда как разорвать связь красиво?
Допустим я следующим образом видоизменю код:
general.h
C++ | ||
|
general.cpp
C++ | ||
|
cl.h
C++ | ||
|
Тогда в выводе я получаю:
Кликните здесь для просмотра всего текста
====================[ Build | pr1 | Debug ]=====================================
«C:Program FilesJetBrainsCLion 2019.3.3bincmakewinbincmake.exe» —build K:devcpppr1cmake-build-debug —target pr1 — -j 2
Scanning dependencies of target pr1
[ 28%] Building CXX object CMakeFiles/pr1.dir/main.cpp.obj
[ 28%] Building CXX object CMakeFiles/pr1.dir/general.cpp.obj
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:9: error: ‘cl’ was not declared in this scope
int sum(cl ob);
^~
In file included from K:devcpppr1main.cpp:6:
K:devcpppr1cl.h:15:25: error: ‘int sum(cl)’ redeclared as different kind of symbol
friend int sum(cl ob);
^
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:5: note: previous declaration ‘int sum’
int sum(cl ob);
^~~
mingw32-make.exe[3]: *** [CMakeFilespr1.dirbuild.make:62: CMakeFiles/pr1.dir/main.cpp.obj] Error 1
mingw32-make.exe[3]: *** Waiting for unfinished jobs….
mingw32-make.exe[2]: *** [CMakeFilesMakefile2:75: CMakeFiles/pr1.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:82: CMakeFiles/pr1.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: pr1] Error 2
Не понятно почему «error: ‘cl’ was not declared in this scope» ведь я же указал include’ом заголовочный файл cl.h. Судя по документации Еще на этапе препроцессинга этот кусок с определением класса должен попасть в general.h и значит определение в месте с ним.
Но если я сделаю в файле
general.h
C++ | ||
|
и в файле:
general.cpp
C++ | ||
|
, то все работает.
В общем:
1) при компиляции файла general.cpp нужно уже не просто ссылку на имя класса cl, а его определение.
2) при подключении объявлении имен в general.h достаточно знать только лишь ссылки на используемые имена ( определения не обязательно знать )
Но остается недопонимание того, почему при включении в general.h заголовочного файла cl.h происходить ругань:
K:devcpppr1general.h:9:9: error: ‘cl’ was not declared in this scope
Это что выходит, что определение не является объявлением? Мы же туда подставили целое определение…
(см. вложение)
07-04-2013
#1
Registered User
07-05-2013
#8
Registered User
Originally Posted by Elysia
One project = one program.
One program consists of many source files that are merged together into one file (executable). A project is a way to keep all these files together and merge them into a single file.
So, to create a new program, create a new project. That’s all.Technically you could just create a separate CB target for each main function.
Tim S.
«…a computer is a stupid machine with the ability to do incredibly smart things, while computer programmers are smart people with the ability to do incredibly stupid things. They are,in short, a perfect match..» Bill Bryson
Глобальный модератор
Offline
Пол:
Внимание! Люблю сахар в кубиках!
P.S. Разве так сложно написать (компилятору), что он не знает какой main запустить, потому что их больше одного в проекте… Криворукие программисты
а это что написано?
multiple definition of `main’ , first defined here
научись читать. умник нашелся.
можешь спросить, а где номер строчки? и я тебе отвечу, линкер не обязан быть в курсе каким образом были получены объектные файлы, точнее компиляция какой комбинации исходных кодов привела к появлению этих файлов, за это отвечает компилятор.
Вот натолкнулся на проблему: знаю путь к папке, но как проверить, что это именно папка, а не файл?
если линукс, то используем stat
во кусок из BOOST
status_api( const std::string & ph, error_code & ec )
{
struct stat path_stat;
if ( ::stat( ph.c_str(), &path_stat ) != 0 )
{
if ( errno == ENOENT || errno == ENOTDIR )
{
ec = ok;
return fs::file_status( fs::file_not_found );
}
ec = error_code( errno, system_category );
return fs::file_status( fs::status_unknown );
}
ec = ok;
if ( S_ISDIR( path_stat.st_mode ) )
return fs::file_status( fs::directory_file );
if ( S_ISREG( path_stat.st_mode ) )
return fs::file_status( fs::regular_file );
if ( S_ISBLK( path_stat.st_mode ) )
return fs::file_status( fs::block_file );
if ( S_ISCHR( path_stat.st_mode ) )
return fs::file_status( fs::character_file );
if ( S_ISFIFO( path_stat.st_mode ) )
return fs::file_status( fs::fifo_file );
if ( S_ISSOCK( path_stat.st_mode ) )
return fs::file_status( fs::socket_file );
return fs::file_status( fs::type_unknown );
}
есть такой кусок для винды, но принцип тот же:
template< class String >
fs::file_status status_template( const String & ph, error_code & ec )
{
DWORD attr( get_file_attributes( ph.c_str() ) );
if ( attr == 0xFFFFFFFF )
{
ec = error_code( ::GetLastError(), system_category );
if ((ec.value() == ERROR_FILE_NOT_FOUND)
|| (ec.value() == ERROR_PATH_NOT_FOUND)
|| (ec.value() == ERROR_INVALID_NAME) // «tools/jam/src/:sys:stat.h», «//foo»
|| (ec.value() == ERROR_INVALID_PARAMETER) // «:sys:stat.h»
|| (ec.value() == ERROR_BAD_PATHNAME) // «//nosuch» on Win64
|| (ec.value() == ERROR_BAD_NETPATH)) // «//nosuch» on Win32
{
ec = ok; // these are not considered errors;
// the status is considered not found
return fs::file_status( fs::file_not_found );
}
else if ((ec.value() == ERROR_SHARING_VIOLATION))
{
ec = ok; // these are not considered errors;
// the file exists but the type is not known
return fs::file_status( fs::type_unknown );
}
return fs::file_status( fs::status_unknown );
}
ec = ok;;
return (attr & FILE_ATTRIBUTE_DIRECTORY)
? fs::file_status( fs::directory_file )
: fs::file_status( fs::regular_file );
}
Перейти к контенту
otreblA_SNAKE_[ITA]
Hi there guys,
I’m studying C++ with Deitel «C++ How To Program» and I’ve done a small «gradebook» program. However I’ve a problem: when I try tu build&run my program I’ve an error:
C:UsersAlbertoAppDataLocalTempccSdybij.o:main.cpp|| multiple definition of `main’|
objDebugmain.o:C:UsersAlbertoDocumentsProgetti C++ CodeBlocksConsoleApplication24main.cpp|10|first defined here|
||=== Build finished: 2 errors, 0 warnings ===|
Here’s my simple program:
gradebook.h
#include <string>
using std::string;class GradeBook
{
public:
GradeBook( string );
void setCourseName( string );
string getCourseName();
void displayMessage();
private:
string courseName;
};
gradebook.cpp
#include <iostream>
using std::cout;
using std::endl;#include "GradeBook.h"
GradeBook::GradeBook( string name )
{
setCourseName( name );
}
void GradeBook::setCourseName( string name )
{
if ( name.length() <= 25 )
courseName = name;
if ( name.length() > 25 )
{
courseName = name.substr( 0, 25 );
cout << "Name "" << name << "" exceeds maximum lenght (25).n" << "Limiting courseName to first 25 characters.n" << endl;
}
}
string GradeBook::getCourseName()
{
return courseName;
}
void GradeBook::displayMessage()
{
cout << "Welcome to the GradeBook forn" << getCourseName() << "!" << endl;
}
Main.cpp
#include <iostream>
using std::cout;
using std::endl;#include "GradeBook.h"
int main()
{
//creazione di due oggetti GradeBook
GradeBook gradeBook1( "CS101 Introduction to C++ Programming" );
GradeBook gradeBook2( "CS102 Data Structures in C++" );
cout << "gradeBook1's initial name is: " << gradeBook1.getCourseName() << "ngradeBook2's initial name is: " << gradeBook2.getCourseName() << endl;
gradeBook1.setCourseName( "CS101 C++ Programming" );
cout << "ngradeBook1's course name is: " << gradeBook1.getCourseName() << "ngradeBook2's course name is: " << gradeBook2.getCourseName() << endl;
return 0;
}
In my «Linker Settings» I’ve included both gradebook.h and gradebook.cpp files but that doesn’t help
Thank you,
otreblA
« Last Edit: June 23, 2010, 11:40:07 am by otreblA_SNAKE_[ITA] »
Logged
Я часами застреваю над проблемой, которая, вероятно, очень тривиальна.
Это самое основное использование классов.
Заголовочный файл: person.h
class person
{
protected:
std::string _Name;
public:
void setName(std::string);
};
Реализация: person.cpp
#include <string>
#include "person.h"
void person::setName(std::string name)
{
_Name = name;
}
Драйвер: main.cpp
#include <iostream>
#include "person.cpp"
int main()
{
std::cout << "Yes, it worked.n";
return 0;
}
При попытке скомпилировать этот код в CodeBlocks (используя GNU GCC), я получаю сообщение об ошибке:
~person.cpp|5|multiple definition of `person::setName(std::string)'|
~person.cpp|5|first defined here|
||=== Build finished: 2 errors, 0 warnings (0 minutes, 0 seconds) ===|
У меня есть прототип в заголовочном файле и тело в файле реализации. Где множественное определение? Это работает, если я добавлю «inline» перед «void» в person.cpp, но зачем мне в этом случае?
Кроме того, при компиляции того же точного кода в cmd, что и «g ++ main.cpp -o main.exe», он работает отлично (без встроенного)!
2
Решение
Вам не нужно включать *.cpp
файл в main.cpp. Вы должны включить *.h
файл.
Короче — *.cpp
Файлы содержат реализацию и скомпилированы компилятором. *.h
файлы содержат определения и могут быть включены из *.cpp
файлы. Когда вы включаете *.cpp
файл, вы получите несколько определений одного и того же объекта.
Кроме того, вам нужно добавить включить охрану
#ifndef MY_HEADER
#define MY_HEADER
... code of your header file ...
#endif
или просто добавь
#pragma once
если ваш компилятор поддерживает это.
4
Другие решения
произошло ли это сегодня.
при добавлении файла в кодовые блоки с помощью file — new и т. д. появляется экран, который спрашивает, хотите ли вы включить файл в отладочную и выпускную версии. Вы невинно отвечаете «да», ставя галочки. в результате файл автоматически включается, и когда вы явно включаете его самостоятельно, вы в конечном итоге дублируете. поэтому не ставьте галочки в этих клетках.
ура
толстяк-коротышка
2
Вы можете включить файл .cpp в другой .cpp в кодовых блоках. Но не добавляйте его в проект, который вы создали. Если файл включен в проект, блоки кода будут пытаться скомпилировать его следующим образом:
g ++ main.cpp -o main.o
g ++ person.cpp -o person.o
и затем создайте окончательный выходной файл, используя два .o файла. Поскольку main.cpp включает в себя func.cpp, вы столкнетесь с ошибкой множественного объявления.
Теперь, если вы оставите в проекте только файл main.cpp, только он будет скомпилирован, и вы не получите ту же ошибку.
0
Антон (LogRus)
Глобальный модератор
Offline
Пол:
Внимание! Люблю сахар в кубиках!
P.S. Разве так сложно написать (компилятору), что он не знает какой main запустить, потому что их больше одного в проекте… Криворукие программисты
а это что написано?
multiple definition of `main’ , first defined here
научись читать. умник нашелся.
можешь спросить, а где номер строчки? и я тебе отвечу, линкер не обязан быть в курсе каким образом были получены объектные файлы, точнее компиляция какой комбинации исходных кодов привела к появлению этих файлов, за это отвечает компилятор.
Вот натолкнулся на проблему: знаю путь к папке, но как проверить, что это именно папка, а не файл?
если линукс, то используем stat
во кусок из BOOST
status_api( const std::string & ph, error_code & ec )
{
struct stat path_stat;
if ( ::stat( ph.c_str(), &path_stat ) != 0 )
{
if ( errno == ENOENT || errno == ENOTDIR )
{
ec = ok;
return fs::file_status( fs::file_not_found );
}
ec = error_code( errno, system_category );
return fs::file_status( fs::status_unknown );
}
ec = ok;
if ( S_ISDIR( path_stat.st_mode ) )
return fs::file_status( fs::directory_file );
if ( S_ISREG( path_stat.st_mode ) )
return fs::file_status( fs::regular_file );
if ( S_ISBLK( path_stat.st_mode ) )
return fs::file_status( fs::block_file );
if ( S_ISCHR( path_stat.st_mode ) )
return fs::file_status( fs::character_file );
if ( S_ISFIFO( path_stat.st_mode ) )
return fs::file_status( fs::fifo_file );
if ( S_ISSOCK( path_stat.st_mode ) )
return fs::file_status( fs::socket_file );
return fs::file_status( fs::type_unknown );
}
есть такой кусок для винды, но принцип тот же:
template< class String >
fs::file_status status_template( const String & ph, error_code & ec )
{
DWORD attr( get_file_attributes( ph.c_str() ) );
if ( attr == 0xFFFFFFFF )
{
ec = error_code( ::GetLastError(), system_category );
if ((ec.value() == ERROR_FILE_NOT_FOUND)
|| (ec.value() == ERROR_PATH_NOT_FOUND)
|| (ec.value() == ERROR_INVALID_NAME) // «tools/jam/src/:sys:stat.h», «//foo»
|| (ec.value() == ERROR_INVALID_PARAMETER) // «:sys:stat.h»
|| (ec.value() == ERROR_BAD_PATHNAME) // «//nosuch» on Win64
|| (ec.value() == ERROR_BAD_NETPATH)) // «//nosuch» on Win32
{
ec = ok; // these are not considered errors;
// the status is considered not found
return fs::file_status( fs::file_not_found );
}
else if ((ec.value() == ERROR_SHARING_VIOLATION))
{
ec = ok; // these are not considered errors;
// the file exists but the type is not known
return fs::file_status( fs::type_unknown );
}
return fs::file_status( fs::status_unknown );
}
ec = ok;;
return (attr & FILE_ATTRIBUTE_DIRECTORY)
? fs::file_status( fs::directory_file )
: fs::file_status( fs::regular_file );
}
Undisputed, ну тогда как разорвать связь красиво?
Допустим я следующим образом видоизменю код:
general.h
C++ | ||
|
general.cpp
C++ | ||
|
cl.h
C++ | ||
|
Тогда в выводе я получаю:
Кликните здесь для просмотра всего текста
====================[ Build | pr1 | Debug ]=====================================
«C:Program FilesJetBrainsCLion 2019.3.3bincmakewinbincmake.exe» —build K:devcpppr1cmake-build-debug —target pr1 — -j 2
Scanning dependencies of target pr1
[ 28%] Building CXX object CMakeFiles/pr1.dir/main.cpp.obj
[ 28%] Building CXX object CMakeFiles/pr1.dir/general.cpp.obj
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:9: error: ‘cl’ was not declared in this scope
int sum(cl ob);
^~
In file included from K:devcpppr1main.cpp:6:
K:devcpppr1cl.h:15:25: error: ‘int sum(cl)’ redeclared as different kind of symbol
friend int sum(cl ob);
^
In file included from K:devcpppr1cl.h:9,
from K:devcpppr1main.cpp:6:
K:devcpppr1general.h:12:5: note: previous declaration ‘int sum’
int sum(cl ob);
^~~
mingw32-make.exe[3]: *** [CMakeFilespr1.dirbuild.make:62: CMakeFiles/pr1.dir/main.cpp.obj] Error 1
mingw32-make.exe[3]: *** Waiting for unfinished jobs….
mingw32-make.exe[2]: *** [CMakeFilesMakefile2:75: CMakeFiles/pr1.dir/all] Error 2
mingw32-make.exe[1]: *** [CMakeFilesMakefile2:82: CMakeFiles/pr1.dir/rule] Error 2
mingw32-make.exe: *** [Makefile:117: pr1] Error 2
Не понятно почему «error: ‘cl’ was not declared in this scope» ведь я же указал include’ом заголовочный файл cl.h. Судя по документации Еще на этапе препроцессинга этот кусок с определением класса должен попасть в general.h и значит определение в месте с ним.
Но если я сделаю в файле
general.h
C++ | ||
|
и в файле:
general.cpp
C++ | ||
|
, то все работает.
В общем:
1) при компиляции файла general.cpp нужно уже не просто ссылку на имя класса cl, а его определение.
2) при подключении объявлении имен в general.h достаточно знать только лишь ссылки на используемые имена ( определения не обязательно знать )
Но остается недопонимание того, почему при включении в general.h заголовочного файла cl.h происходить ругань:
K:devcpppr1general.h:9:9: error: ‘cl’ was not declared in this scope
Это что выходит, что определение не является объявлением? Мы же туда подставили целое определение…
(см. вложение)
Я часами застреваю над проблемой, которая, вероятно, очень тривиальна.
Это самое основное использование классов.
Заголовочный файл: person.h
class person
{
protected:
std::string _Name;
public:
void setName(std::string);
};
Реализация: person.cpp
#include <string>
#include "person.h"
void person::setName(std::string name)
{
_Name = name;
}
Драйвер: main.cpp
#include <iostream>
#include "person.cpp"
int main()
{
std::cout << "Yes, it worked.n";
return 0;
}
При попытке скомпилировать этот код в CodeBlocks (используя GNU GCC), я получаю сообщение об ошибке:
~person.cpp|5|multiple definition of `person::setName(std::string)'|
~person.cpp|5|first defined here|
||=== Build finished: 2 errors, 0 warnings (0 minutes, 0 seconds) ===|
У меня есть прототип в заголовочном файле и тело в файле реализации. Где множественное определение? Это работает, если я добавлю «inline» перед «void» в person.cpp, но зачем мне в этом случае?
Кроме того, при компиляции того же точного кода в cmd, что и «g ++ main.cpp -o main.exe», он работает отлично (без встроенного)!
2
Решение
Вам не нужно включать *.cpp
файл в main.cpp. Вы должны включить *.h
файл.
Короче — *.cpp
Файлы содержат реализацию и скомпилированы компилятором. *.h
файлы содержат определения и могут быть включены из *.cpp
файлы. Когда вы включаете *.cpp
файл, вы получите несколько определений одного и того же объекта.
Кроме того, вам нужно добавить включить охрану
#ifndef MY_HEADER
#define MY_HEADER
... code of your header file ...
#endif
или просто добавь
#pragma once
если ваш компилятор поддерживает это.
4
Другие решения
произошло ли это сегодня.
при добавлении файла в кодовые блоки с помощью file — new и т. д. появляется экран, который спрашивает, хотите ли вы включить файл в отладочную и выпускную версии. Вы невинно отвечаете «да», ставя галочки. в результате файл автоматически включается, и когда вы явно включаете его самостоятельно, вы в конечном итоге дублируете. поэтому не ставьте галочки в этих клетках.
ура
толстяк-коротышка
2
Вы можете включить файл .cpp в другой .cpp в кодовых блоках. Но не добавляйте его в проект, который вы создали. Если файл включен в проект, блоки кода будут пытаться скомпилировать его следующим образом:
g ++ main.cpp -o main.o
g ++ person.cpp -o person.o
и затем создайте окончательный выходной файл, используя два .o файла. Поскольку main.cpp включает в себя func.cpp, вы столкнетесь с ошибкой множественного объявления.
Теперь, если вы оставите в проекте только файл main.cpp, только он будет скомпилирован, и вы не получите ту же ошибку.
0
Я застрял часами по проблеме, которая, вероятно, очень тривиальна.
Это самое основное использование классов.
Заголовок файла: person.h
class person
{
protected:
std::string _Name;
public:
void setName(std::string);
};
Реализация: person.cpp
#include <string>
#include "person.h"
void person::setName(std::string name)
{
_Name = name;
}
Драйвер: main.cpp
#include <iostream>
#include "person.cpp"
int main()
{
std::cout << "Yes, it worked.n";
return 0;
}
При попытке скомпилировать этот код в CodeBlocks (используя GNU GCC), я получаю сообщение об ошибке:
~person.cpp|5|multiple definition of 'person::setName(std::string)'|
~person.cpp|5|first defined here|
||=== Build finished: 2 errors, 0 warnings (0 minutes, 0 seconds) ===|
У меня есть прототип в файле заголовка и тело в файле реализации. Где множественное определение? Он работает, если я добавлю «inline» перед «void» в person.cpp, но почему я должен в этом случае?
Кроме того, при компиляции этого же точного кода в cmd как «g++ main.cpp -o main.exe», он отлично работает (без встроенного)!
I found something that at least begins to answer my own question. The following two links have wmv files from Microsoft that demonstrate using a C# class in unmanaged C++.
This first one uses a COM object and regasm: http://msdn.microsoft.com/en-us/vstudio/bb892741.
This second one uses the features of C++/CLI to wrap the C# class: http://msdn.microsoft.com/en-us/vstudio/bb892742. I have been able to instantiate a c# class from managed code and retrieve a string as in the video. It has been very helpful but it only answers 2/3rds of my question as I want to instantiate a class with a string perimeter into a c# class. As a proof of concept I altered the code presented in the example for the following method, and achieved this goal. Of course I also added a altered the {public string PickDate(string Name)} method to do something with the name string to prove to myself that it worked.
wchar_t * DatePickerClient::pick(std::wstring nme)
{
IntPtr temp(ref);// system int pointer from a native int
String ^date;// tracking handle to a string (managed)
String ^name;// tracking handle to a string (managed)
name = gcnew String(nme.c_str());
wchar_t *ret;// pointer to a c++ string
GCHandle gch;// garbage collector handle
DatePicker::DatePicker ^obj;// reference the c# object with tracking handle(^)
gch = static_cast<GCHandle>(temp);// converted from the int pointer
obj = static_cast<DatePicker::DatePicker ^>(gch.Target);
date = obj->PickDate(name);
ret = new wchar_t[date->Length +1];
interior_ptr<const wchar_t> p1 = PtrToStringChars(date);// clr pointer that acts like pointer
pin_ptr<const wchar_t> p2 = p1;// pin the pointer to a location as clr pointers move around in memory but c++ does not know about that.
wcscpy_s(ret, date->Length +1, p2);
return ret;
}
Part of my question was: What is better? From what I have read in many many efforts to research the answer is that COM objects are considered easier to use, and using a wrapper instead allows for greater control. In some cases using a wrapper can (but not always) reduce the size of the thunk, as COM objects automatically have a standard size footprint and wrappers are only as big as they need to be.
The thunk (as I have used above) refers to the space time and resources used in between C# and C++ in the case of the COM object, and in between C++/CLI and native C++ in the case of coding-using a C++/CLI Wrapper. So another part of my answer should include a warning that crossing the thunk boundary more than absolutely necessary is bad practice, accessing the thunk boundary inside a loop is not recommended, and that it is possible to set up a wrapper incorrectly so that it double thunks (crosses the boundary twice where only one thunk is called for) without the code seeming to be incorrect to a novice like me.
Two notes about the wmv’s. First: some footage is reused in both, don’t be fooled. At first they seem the same but they do cover different topics. Second, there are some bonus features such as marshalling that are now a part of the CLI that are not covered in the wmv’s.
Edit:
Note there is a consequence for your installs, your c++ wrapper will not be found by the CLR. You will have to either confirm that the c++ application installs in any/every directory that uses it, or add the library (which will then need to be strongly named) to the GAC at install time. This also means that with either case in development environments you will likely have to copy the library to each directory where applications call it.