2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение02.11.2009, 21:19 


26/03/09
97
Мне необходимо было написать функцию на ассемблере и использовать её (объектный файл с ней) в коде С++ проекта Windows Forms на Microsoft Visual Studio Team System 2008.

Я делал это так:

Visual Studio 2008 NASM integration

In order to use nasm seamlessly in your VS2k8, follow the steps below.

1. First install nasm by running its installer
2. copy nasm.rules to c:\Program Files\Microsoft Visual Studio 2008\VC\VCProjectDefaults
3. Start Visual Studio 2008
4. go to Tools->Options->VC++ Directories
5. click on Show Directories for Executables
6. add C:\Program Files\NASM to the list of paths
7. Open a solution that you want to use NASM with
8. Right click on the project name and select Custom Build Rules
9. Check the box next to the NASM line
10. Add any .asm files to the project
11. click on build to test

Содержание файла nasm.rules:
код: [ скачать ] [ спрятать ]
Используется синтаксис XML
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile
        Name="Netwide Macro Assembler"
        Version="8.00"
        >
        <Rules>
                <CustomBuildRule
                        Name="NASM"
                        DisplayName="Netwide Macro Assembler"
                        CommandLine="nasm.exe -f win32 -Xvc [AllOptions] [AdditionalOptions] [Inputs]"
                        Outputs="[$ObjectFileName]"
                        FileExtensions="*.asm"
                        ExecutionDescription="Assembling..."
                        >
                        <Properties>
                                <StringProperty
                                        Name="ObjectFileName"
                                        DisplayName="Object File Name"
                                        PropertyPageName="Object File"
                                        Description="Specifies the name of the output object file.     (-o [file])"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-o &quot;[value]&quot;"
                                        DefaultValue="<img src='https://dxdy-04.korotkov.co.uk/f/3/0/5/305367720ef5c633c6a4083e46e6f75e82.png'  class="latex" alt="$(IntDir)\$" title="$(IntDir)\$" />(InputName).obj"
                                />
                                <StringProperty
                                        Name="PreprocessorDefinitions"
                                        DisplayName="Preprocessor Definitions"
                                        Description="Defines a text macro with the given name.     (-D[symbol])"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-D[value]"
                                        Delimited="false"
                                        Inheritable="true"
                                />
                                <StringProperty
                                        Name="UndefinePreprocessorDefinitions"
                                        DisplayName="Undefine Preprocessor Definitions"
                                        Description="Undefines a text macro with the given name.     (-U[symbol])"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-U[value]"
                                        Delimited="false"
                                        Inheritable="true"
                                />
                                <StringProperty
                                        Name="AssembledCodeListingFile"
                                        DisplayName="Assembled Code Listing File"
                                        PropertyPageName="Listing File"
                                        Description="Generates an assembled code listing file.     (-l [file])"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-l &quot;[value]&quot;"
                                />
                                <StringProperty
                                        Name="IncludePaths"
                                        DisplayName="Include Paths"
                                        Description="Sets path for include file.     (-I[path])"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-I[value]"
                                        Delimited="false"
                                        Inheritable="true"
                                />
                                <BooleanProperty
                                        Name="TreatWarningsAsErrors"
                                        DisplayName="Treat Warnings As Errors"
                                        Description="Returns an error code if warnings are generated.     (-Werror)"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-Werror"
                                />
                                <BooleanProperty
                                        Name="GenerateDebugInformation"
                                        DisplayName="Generate Debug Information"
                                        Description="Generates Debug Information.     (-g)"
                                        HelpURL="http://www.nasm.us/doc/"
                                        Switch="-g"
                                        DefaultValue="true"
                                />
                               
                        </Properties>
                </CustomBuildRule>
        </Rules>
</VisualStudioToolFile>
 

_________________________________________________

В *.asm файле функция объявлена так:

global _myFunc@1

В файле Form1.h я написал следующее объявление:

extern "C" myStruct * __stdcall myFunc(int) ;

Когда добавляю к проекту *.asm файл и запускаю построение проекта объектный файл скомпилированый nasm.exe появляется в папке
D:\NASM\МОИ ПРОГРАММЫ\Visual Studio 2008\Projects\Memory Damp\Memory Damp\Debug
__________________________________________________

Но при компоновке получаются следующие ошибки:
Код:
Ошибка   3   error LNK2028: ссылка на неразрешенную лексему (0A00048D) "extern "C" struct myStruct * __stdcall myFunc(int)" (?myFunc@@$$J14YGPAUmyStruct@@H@Z) в функции "private: void __clrcall MemoryDamp::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@MemoryDamp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)   Memory Damp.obj   Memory Damp

Ошибка   4   error LNK2028: ссылка на неразрешенную лексему (0A0004AE) "void __stdcall _com_issue_error(long)" (?_com_issue_error@@$$FYGXJ@Z) в функции "void __cdecl _com_util::CheckError(long)" (?CheckError@_com_util@@$$FYAXJ@Z)   Memory Damp.obj   Memory Damp

Ошибка   5   error LNK2019: ссылка на неразрешенный внешний символ "void __stdcall _com_issue_error(long)" (?_com_issue_error@@$$FYGXJ@Z) в функции "void __cdecl _com_util::CheckError(long)" (?CheckError@_com_util@@$$FYAXJ@Z)   Memory Damp.obj   Memory Damp

Ошибка   6   error LNK2019: ссылка на неразрешенный внешний символ "extern "C" struct myStruct * __stdcall myFunc(int)" (?myFunc@@$$J14YGPAUmyStruct@@H@Z) в функции "private: void __clrcall MemoryDamp::Form1::button1_Click(class System::Object ^,class System::EventArgs ^)" (?button1_Click@Form1@MemoryDamp@@$$FA$AAMXP$AAVObject@System@@P$AAVEventArgs@4@@Z)   Memory Damp.obj   Memory Damp

Ошибка   7   fatal error LNK1120: 4 неразрешенных внешних элементов   D:\NASM\МОИ ПРОГРАММЫ\Visual Studio 2008\Projects\Memory Damp\Debug\Memory Damp.exe   Memory Damp

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение02.11.2009, 22:03 
Заслуженный участник


09/08/09
3438
С.Петербург
А Вы уверены, что такая связка возможна для managed приложений?
Может быть, в этом случае надо линковать Ваш ассемблерный модуль в DLL и дергать его через [DllImport]?

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение02.11.2009, 22:37 
Заслуженный участник


28/04/09
1933
Не проще ли воспользоваться конструкцией asm (_asm, __asm)? Особливо ежели планируемая к прилинковыванию функция столь одинока?

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 00:56 
Заслуженный участник


09/08/09
3438
С.Петербург
Charlie в сообщении #257713 писал(а):
Мне необходимо было написать функцию на ассемблере и использовать её (объектный файл с ней) в коде С++ проекта Windows Forms

Charlie, извините за любопытство, а при решении какой задачи возникла такая необходимость?

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 04:26 


26/03/09
97
Задача пока учебная. Использую NASM. Встроеный компилятор я где-то прочитал заменить на NASM нельзя.
Хотел подключить статические библиотеки функций к проекту как описано в книге:
Юрий Магда "Ассемблер для процессоров Intel Pentium" Глава 10.3 Интерфейс ассемблерных процедур с Visual C++ .NET 2005.

Теперь буду пробовать писать динамическую библиотеку.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 10:33 
Заслуженный участник


09/08/09
3438
С.Петербург
Charlie в сообщении #257798 писал(а):
Хотел подключить статические библиотеки функций к проекту как описано в книге:
Юрий Магда "Ассемблер для процессоров Intel Pentium" Глава 10.3 Интерфейс ассемблерных процедур с Visual C++ .NET 2005.
Там в качестве вызывающей программы используется обычное приложение (не managed).

Charlie в сообщении #257798 писал(а):
Теперь буду пробовать писать динамическую библиотеку.
Ну здесь-то проблем быть не должно.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 19:44 
Заслуженный участник


15/05/09
1563
Компоновщик ищет глобальный симвло ?myFunc@@, соответствующий с его точки зрения объявлению "extern "C" struct myStruct * __stdcall myFunc(int)", однако Вы объявляете в ассемблерном модуле функцию как _myFunc@1. Здесь все в порядке? Я не использую Visual Studio, поэтому не в курсе подробностей именования внешних символов компиляторами, но если я не ошибаюсь, ассемблер и компилятор C генерируют разные внешние символы: ?myFunc@@ и _myFunc@1.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 20:41 
Заслуженный участник


09/08/09
3438
С.Петербург
PapaKarlo в сообщении #258014 писал(а):
Компоновщик ищет глобальный симвло ?myFunc@@, соответствующий с его точки зрения объявлению "extern "C" struct myStruct * __stdcall myFunc(int)"

Компоновщик ищет ещё более страшный глобальный символ: ?myFunc@@[math]$$J14YGPAUmyStruct@@H@Z.
Это стандартный способ переименования функций компилятором С++, обеспечивающий разные внешние имена для перегруженных функций. По идее, описатель 'extern "C"', указанный в прототипе для MyFunc, должен блокировать такое переименование (так что соответствующий внешний символ должен превращаться просто в _MyFunc), но для .Net-приложений это не срабатывает.

-- Вт ноя 03, 2009 20:53:36 --

Другими словами, управляемый (managed) и неуправляемый (unmanaged) код компилируется в .Net-приложениях по-разному:
Код:
#include "stdafx.h"
using namespace System;

extern "C" int MyFunc(int);

#pragma managed(push, off)
// Неуправляемый (unmanaged) код
void test()
{
    MyFunc(1); // компилируется в вызов _MyFunc
}
#pragma managed(pop)

// Управляемый (unmanaged) код
int main(array<System::String ^> ^args)
{
    MyFunc(1) ; // компилируется в вызов ?MyFunc@@$$[/math]J0YAHH@Z
    test();
    return 0;
}

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение03.11.2009, 22:52 
Заслуженный участник


15/05/09
1563
Maslov в сообщении #258042 писал(а):
Компоновщик ищет ещё более страшный глобальный символ: ?myFunc@@[math]$$J14YGPAUmyStruct@@H@Z
Ну да, так и есть. Уж больно любопытно предтавляет использованный Charlie тег сообщения компоновщика. :)

Если имя символа генерируется в зависимости от контекста заголовка, в котором объявлен этот символ, то надо и в ассемблерном тексте также объявлять. Но это означает лишь головную боль - зачем брать на себя работу компилятора? Гораздо проще написать unmanaged код C-посредника, который будет вызвать ассемблерную процедуру.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение04.11.2009, 00:48 
Заслуженный участник


09/08/09
3438
С.Петербург
PapaKarlo в сообщении #258083 писал(а):
Но это означает лишь головную боль - зачем брать на себя работу компилятора? Гораздо проще написать unmanaged код C-посредника, который будет вызвать ассемблерную процедуру.

Конечно. Но насколько я понимаю, это учебная задача как раз для головной боли :). У меня, например, за всю многолетнюю историю общения с .Net ни разу не возникла необходимость включать в managed приложения ассемблерные функции. Как, впрочем, и не возникло желания написать что-нибудь на managed C++ :).

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение04.11.2009, 18:23 


26/03/09
97
Да, как-то не оптимально получается писать функцию в unmanaged для того только чтобы из неё вызвать другую функцию.

Но не знаю закрывать тему или нет, потому что я сдлал по совету Maslov а компоновщик начал ругаться уже подругому:

Код:

В ассемблере:

global _myFunc@4


В С++ :

using namespace System;

extern "C" myStruct * __stdcall myFunc(int) ;

#pragma managed(push, off)

    myStruct * intermediateFunc(int a)
       { return myFunc(a) ; }

#pragma managed(pop)
............................................

Ошибка   3   error LNK2028: ссылка на неразрешенную лексему (0A0004AF) "void __stdcall _com_issue_error(long)" (?_com_issue_error@@$$FYGXJ@Z) в функции "void __cdecl _com_util::CheckError(long)" (?CheckError@_com_util@@$$FYAXJ@Z)   Memory Damp.obj   Memory Damp

Ошибка   4   error LNK2019: ссылка на неразрешенный внешний символ "void __stdcall _com_issue_error(long)" (?_com_issue_error@@$$FYGXJ@Z) в функции "void __cdecl _com_util::CheckError(long)" (?CheckError@_com_util@@$$FYAXJ@Z)   Memory Damp.obj   Memory Damp

Ошибка   5   fatal error LNK1120: 2 неразрешенных внешних элементов   D:\NASM\МОИ ПРОГРАММЫ\Visual Studio 2008\Projects\Memory Damp\Debug\Memory Damp.exe   Memory Damp



Похоже что с ассемблерной функцией теперь всё в порядке, но теперь проблема с какой-то функцией CheckError. Это не моя функция - я её нигде не писал и не использовал.
______________________________________

Ошибка средств компоновщика LNK2028:

Сообщение об ошибке
"exported_function" (decorated_name) в функции "function_containing_function_call" (decorated_name)
"exported_function" (decorated_name) referenced in function "function_containing_function_call" (decorated_name)

При попытке импортирования внутренней функции в чистый образ следует помнить о том, что явный вызов соглашений отличается во внутренней и чистой компиляции.

Пример
В примере этого кода создается компонент с экспортированной и внутренней функцией, явно вызывающий соглашение __cdecl.

Код:
// LNK2028.cpp
// compile with: /LD
__declspec(dllexport) int func() {
   return 3;
}


В следующем примере создается чистый клиент, использующий внутреннюю функцию. Однако вызов соглашения в /clr:pure представляет из себя __clrcall. Следующий пример приводит к возникновению ошибки LNK2028.

Код:
// LNK2028_b.cpp
// compile with: /clr:pure lnk2028.lib
// LNK2028 expected
int func();

int main() {
   return func();
}


Ошибка средств компоновщика LNK2019:

Сообщение об ошибке
ссылка на неразрешенный внешний символ "символ" в функции "функция".
unresolved external symbol 'symbol' referenced in function 'function'.

Обнаружен неопределенный внешний символ (symbol) в function. Чтобы устранить эту ошибку, предоставьте определение для символа или удалите код, который на него ссылается. Дополнительные сведения см. в следующих разделах:
...

-- Ср ноя 04, 2009 20:18:41 --

Нашёл ! Тут: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/a87f6d96-4850-4bdf-bfcf-9827371e1bd2

This seems to be a calling convention problem, since _com_issue_error explicity use __stdcall calling convention, but when you use /clr switch, all functions are compiled as managed by default, so I suggest you to add #pgrama directive to switch off managed compilation against the function where _com_util::CheckError is called, try add following code:

Code Snippet
Код:
#pragma managed(push,off)

//the function body where you call _com_util::CheckError

#pragma managed(pop)


I am sure you forget to add comsupp.lib to your project's additional dependencies, try add following code to places that before you use _com_util:

Code Snippet
Код:
#pragma comment(lib,"comsupp.lib")


Я так и сделал:

Код:
using namespace System;

extern "C" myStruct * __stdcall myFunc(int) ;

#pragma managed(push, off)
#pragma comment(lib,"comsupp.lib")

    myStruct * intermediateFunc(int a)
       { return myFunc(a) ; }

#pragma managed(pop)


Проект построился. Но...

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение04.11.2009, 19:37 


26/03/09
97
...При запуске программы появляется окно:

Debug Assertion Failed !

Program: ...\...\Memory Damp.exe (моя программа)
File: f:\dd\vctools\crt_bld\self_x86\crt\src\dbgheap.c
Line: 1511
Expression: _CrtIsValidHeapPointer(UserData)
...

Буду разбираться.

-- Ср ноя 04, 2009 20:48:00 --

Line: 1511 _ASSERTE(_CrtIsValidHeapPointer(pUserData));

Странно, код который я написал ничего не делает пока я не нажму кнопку. А тут при запуске программы.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение05.11.2009, 00:27 
Заслуженный участник


09/08/09
3438
С.Петербург
Charlie в сообщении #258313 писал(а):
я сдлал по совету Maslov а компоновщик начал ругаться уже подругому

Charlie, наверное я не очень внятно изложил свой совет.
На самом деле, я предлагал следующее:
1. Построить из Вашей ассемблерной функции отдельную динамически загружаемую библиотеку (например, MyFunc.dll). При этом никаких lib-файлов к ней делать не надо.
2. В программе на C++ описать ассемблерную функцию с использованием атрибута DllImportAttribute:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
using namespace System;
using namespace System::Runtime::InteropServices;

value class MyDll {
public:
    [DllImport("MyFunc.dll")]
    static int MyFunc(int arg);
};

int main(array<System::String ^> ^args)
{
    int res = MyDll::MyFunc(1);
    Console::WriteLine(L"Result of call to MyDll::MyFunc is {0}", res);
    return 0;
}
 
3. Подложить MyFunc.dll в каталог, в котором находится главное приложение на C++, и запустить это главное приложение.

И еще несколько советов.
Во-первых, передача данных по адресу между managed и unmanaged кодом - это отдельная проблема, поэтому лучше начните с более простой ассемблерной функции, например, возвращающей результат типа int.
Во-вторых, в качестве вызывающего managed приложения удобнее использовать консольное приложение (как в моем примере).

И все-таки, если не секрет, зачем Вам нужна такая связка? :)

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение05.11.2009, 04:58 


26/03/09
97
Maslov в сообщении #258443 писал(а):
И все-таки, если не секрет, зачем Вам нужна такая связка? :)


Вы спрашиваете почему я ипользую прект Windows Forms ?
- Я только начинаю изучать Visual Studio .NET . А в других проектах нет визуальной разработки (или я не нашёл) - взял и перетащил мышкой например кнопку или TextBox куда нужно, написал обработчик события... и т.д. Очень просто визуализировать результаты работы ассемблерного кода. Проще чем писать оконное приложение на ассемблере.

 Профиль  
                  
 
 Re: Подключение объектных файлов к проекту на Visual Studio 2008
Сообщение05.11.2009, 09:20 
Заслуженный участник


19/07/08
1266
Charlie в сообщении #258476 писал(а):
Очень просто визуализировать результаты работы ассемблерного кода.
А вызывать функцию -- это часть задания? В смысле, надо много раз вызывать функцию чтобы что-то посчитать или функция вызывается некоторое (небольшое) количестао раз? Просто во втором случае не обязательно вызывать функцию. Можно запустить ассемблерную часть как отдельное приложение. (ну или в отдельном треде, но тут я не советчик) Передать же данные можно массой способов. Начать можно с того, что .NET приложение будет тупо читать данные в том виде, в каком они выводились раньше.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 17 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group