Форум программистов, компьютерный форум CyberForum.ru

Задать параметр для компоновщика в VS - C++

Восстановить пароль Регистрация
 
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
12.03.2012, 14:40     Задать параметр для компоновщика в VS #1
Рассматриваю один из примеров Петзолда где общая память расшаривается через библиотеку для нескольких экземпляров приложения, вот только если у Петзолда она расшаривается то у меня нет (одновременно запущенные экземпляры приложения не видят данных других экземпляров). Единственное что я не сделал к этому примеру это:
Код
Компоновщику необходимо сообщить об области памяти shared. В командной строке компоновщика задайте
параметр -SECTION следующим образом:
-SECTION: shared, rws
Буквы "rws" обозначают, что область памяти имеет атрибуты для чтения (read), записи (write) и разделения (shared)
данных.
Где это делается в vs 6.0? Я с 7ки могу настраивать компиляцию в vs 6.0 только через её интерфейс. Mak файлы не находят vs 6.0. Предполагаю что в настройках проекта где-то должен же быть пункт какой, но что-то не могу найти куда дописывать то что указал Петзолд.
Могу привести код либы и проекта (они совсем небольшие, всё предельно просто), если это необходимо.
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
-=ЮрА=-
Заблокирован
Автор FAQ
13.03.2012, 10:10     Задать параметр для компоновщика в VS #2
Gepar, думаю тебе надо создать в памяти зашареную область для HINSTANCE процесса
Смотри что следует записать в коде DLL
C
1
2
3
4
5
6
7
#include "stdafx.h"
#include <stdio.h>
 
#pragma data_seg(".CBTHook")    // секция в памяти общая для всех процессов
HINSTANCE hInstance = NULL; // дескриптор нашего приложения
#pragma data_seg()      // конец секции
#pragma comment(linker, "/section:.CBTHook,rws") // даем права этой секции
Теперь твоя DLL "будет сидеть" всё время в одном месте, сколько бы процессов её не загрузили, это важно.

Теперь о клиенте, думаю можешь столкнуться с некоторыми подводными камнями. Так вот для хук-точек обязательно строй приложение через мьютекс, иначе куча загруженных экземпляров DLL повергнут систему в ступор
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
BOOL Mutex(LPSTR szName)     // проверяет запущена ли уже копия
{
    HANDLE hMutex = CreateMutex (NULL, TRUE, szName);
    if (GetLastError() == ERROR_ALREADY_EXISTS)    
    {
        CloseHandle(hMutex);
        return FALSE;     // уже запущена
    }
    return TRUE; // все путем
}
//Вызов в коде клиента
if(!Mutex("CBTHook"))
{
    cout<<"CBTHook.dll уже в оперативном пространстве\n";
    cout<<"Осуществите её выгрузку\n";
    bContinue = false;
    nRetCode  = 1;
    }
    else
    if(!(bContinue = (hCBTHook = SetCBTHook(hDLL))))

Не по теме:

PS:Раньше отписать я не мог...

Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
13.03.2012, 17:43  [ТС]     Задать параметр для компоновщика в VS #3
-=ЮрА=-, ну код я конкретно Петзолда рассматривал, он там массив pszStrings расшаривал.
Код выглядит так:
Lib.h
C
1
2
3
4
5
6
7
8
typedef BOOL (CALLBACK *PSTRCB) (PSTR, PVOID);
 
#define MAX_STRINGS 256
#define EXPORT __declspec(dllexport)
 
EXPORT BOOL CALLBACK AddString (PSTR);
EXPORT BOOL CALLBACK DeleteString (PSTR);
EXPORT int CALLBACK GetString (PSTRCB, PVOID);
Lib.c
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <windows.h>
#include "strlib.h"
 
#pragma data_seg ("shared")
 
PSTR pszStrings[MAX_STRINGS]={NULL};
int iTotal=0;
 
#pragma data_seg()
 
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
    int i;
 
    switch(fdwReason)
    {
        //Nothing to do whe process (or thread) begins
 
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
        break;
 
    //When process terminates, free any remining blocks
    case DLL_PROCESS_DETACH:
        for(i=0; i<iTotal;i++)
            UnmapViewOfFile(pszStrings[i]);
        break;
    }
 
    return TRUE;
}
 
EXPORT BOOL CALLBACK AddString(PSTR pStringIn)
{
    HANDLE hString;
    PSTR pString;
    int i, iLength, iCompare;
 
    if(iTotal==MAX_STRINGS-1)
        return FALSE;
 
    iLength=strlen(pStringIn);
    if(iLength==0)
        return FALSE;
 
    hString=CreateFileMapping((HANDLE) -1, NULL, PAGE_READWRITE, 0, 1+iLength, NULL);
    
    if(hString==NULL)
        return FALSE;
 
    pString=(PSTR) MapViewOfFile(hString, FILE_MAP_WRITE, 0, 0, 0);
    strcpy(pString, pStringIn);
    AnsiUpper(pString);
 
    for(i=iTotal; i>0; i--)
    {
        iCompare=strcmpi(pStringIn, pszStrings[i-1]);
 
        if(iCompare>=0)
            break;
        
        pszStrings[i]=pszStrings[i-1];
    }
 
    pszStrings[i]=pString;
 
    iTotal++;
    return TRUE;
}
 
EXPORT BOOL CALLBACK DeleteString (PSTR pStringIn)
{
    int i, j, iCompare;
 
    if(0==strlen(pStringIn))
        return FALSE;
 
    for(i=0; i<iTotal; i++)
    {
        iCompare=lstrcmpi(pszStrings[i], pStringIn);
        
        if(iCompare==0)
            break;
    }
 
    //If given string not in list, return without taking action
    if(i==iTotal)
        return FALSE;
 
    //Else free memory occupied by the string and adjust list donward
    UnmapViewOfFile(pszStrings[i]);
 
    for(j=i; i<iTotal;j++)
        pszStrings[j]=pszStrings[j+1];
 
    pszStrings[iTotal--]=NULL; //Destroy unused pointer
    return TRUE;
}
 
EXPORT int CALLBACK GetString (PSTRCB pfnGetStrCallBack, PVOID pParam)
{
    BOOL bReturn;
    int i;
 
    for(i=0;i<iTotal;i++)
    {
        bReturn=pfnGetStrCallBack(pszStrings[i], pParam);
 
        if(bReturn==FALSE)
            return i+1;
    }
    return iTotal;
}
В общем ничего сложного в ней нет. Массив на 256 элементов с возможностью добавлять в него строку, удалять и получать строки.

Далее код использующий эту либу:
ресурсы (меню с двумя пунктами и два диалоговых окна)
Код
#include <windows.h>
#include "main.h"

StrProg MENU
{
	MENUITEM "&Enter!", IDM_ENTER
	MENUITEM "&Delete!", IDM_DELETE
}

EnterDlg DIALOG 24, 24, 190, 44
STYLE WS_POPUP|WS_DLGFRAME
{
	LTEXT "&Enter", 0, 4, 8, 24, 8
	EDITTEXT IDD_STRING, 32, 6, 154, 12
	DEFPUSHBUTTON "Ok", IDOK, 44, 24, 32, 14
	PUSHBUTTON "Cancel", IDCANCEL 114, 24, 32, 14
}

DeleteDlg DIALOG 24, 24, 190, 44
STYLE WS_POPUP|WS_DLGFRAME
{
	LTEXT "&Delete", 0, 4, 8, 28, 8
	EDITTEXT IDD_STRING, 36, 6, 150, 12
	DEFPUSHBUTTON "Ok", IDOK, 44, 24, 32, 14
	PUSHBUTTON "Cancel", IDCANCEL, 114, 24, 32, 14
}
ну и main
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
#define IDM_ENTER 1
#define IDM_DELETE 2
#define IDD_STRING 0x10
 
 
#include <windows.h>
#include <string.h>
#include "main.h"
#include "strlib.h"
 
#define MAXLEN 32
#define WM_DATACHANGE WM_USER
 
typedef struct
{
    HDC hdc;
    int xText;
    int yText;
    int xStart;
    int yStart;
    int xIncr;
    int yIncr;
    int xMax;
    int yMax;
} CBPARAM;
 
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM);
 
char szAppName[]="StrProg";
char szString[MAXLEN];
 
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, PSTR, int iCmdShow)
{
    HWND hwnd;
    MSG msg;
    WNDCLASSEX wndclass;
 
    ZeroMemory(&wndclass,sizeof(wndclass));
    wndclass.cbSize=sizeof(wndclass);
    wndclass.style=CS_HREDRAW|CS_VREDRAW;
    wndclass.lpfnWndProc=WndProc;
    wndclass.hInstance=hInstance;
    wndclass.hIcon=LoadIcon(NULL, IDI_APPLICATION);
    wndclass.hCursor=LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground=(HBRUSH) GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName=szAppName;
    wndclass.lpszClassName=szAppName;
    wndclass.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
 
    RegisterClassEx(&wndclass);
 
    hwnd=CreateWindow(szAppName, "DLL Demo Program", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT,
        NULL, NULL, hInstance, NULL);
    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
 
    while(GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}
 
BOOL CALLBACK DlgProc (HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    switch(iMsg)
    {
    case WM_INITDIALOG:
        SendDlgItemMessage(hDlg, IDD_STRING, EM_LIMITTEXT, MAXLEN-1, 0);
        return TRUE;
    
    case WM_COMMAND:
        switch(wParam)
        {
        case IDOK:
            GetDlgItemText(hDlg, IDD_STRING, szString, MAXLEN);
            EndDialog(hDlg, TRUE);
            return TRUE;
 
        case IDCANCEL:
            EndDialog(hDlg, FALSE);
            return TRUE;
        }
    }
    return FALSE;
}
 
BOOL CALLBACK EnumCallBack(HWND hwnd, LPARAM lParam)
{
    char szClassName[16];
 
    GetClassName(hwnd, szClassName, sizeof(szClassName));
 
    if(0==strcmp(szClassName, szAppName))
        SendMessage(hwnd, WM_DATACHANGE, 0, 0);
    
    return TRUE;
}
 
BOOL CALLBACK GetStrCallBack (PSTR pString, CBPARAM* pcbp)
{
    TextOut (pcbp->hdc, pcbp->xText, pcbp->yText, pString, strlen(pString));
 
    if((pcbp->yText += pcbp->yIncr)>pcbp->yMax)
    {
        pcbp->yText = pcbp->yStart;
        if((pcbp->xText += pcbp->xIncr) > pcbp->xMax)
            return FALSE;
    }
    return TRUE;
}
 
LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
    static HINSTANCE hInst;
    static int cxChar, cyChar, cxClient, cyClient;
    CBPARAM cbparam;
    HDC hdc;
    PAINTSTRUCT ps;
    TEXTMETRIC tm;
 
    switch(iMsg)
    {
    case WM_CREATE:
        hInst=((LPCREATESTRUCT) lParam)->hInstance;
        hdc=GetDC(hwnd);
 
        GetTextMetrics(hdc, &tm);
        cxChar=(int) tm.tmAveCharWidth;
        cyChar=(int) (tm.tmHeight + tm.tmExternalLeading);
 
        ReleaseDC(hwnd, hdc);
 
        return 0;
 
    case WM_COMMAND:
        switch(wParam)
        {
        case IDM_ENTER:
            if(DialogBox(hInst, "EnterDlg", hwnd, &DlgProc))
            {
                if(AddString(szString))
                    EnumWindows(&EnumCallBack, 0);
                else
                    MessageBeep(0);
            }
            break;
 
        case IDM_DELETE:
            if(DialogBox(hInst, "DelteDlg", hwnd, &DlgProc))
            {
                if(DeleteString(szString))
                    EnumWindows(&EnumCallBack, 0);
                else
                    MessageBeep(0);
            }
            break;
        }
        return 0;
 
    case WM_SIZE:
        cxClient=(int) LOWORD (lParam);
        cyClient=(int) HIWORD (lParam);
        return 0;
 
    case WM_DATACHANGE:
        InvalidateRect(hwnd, NULL, TRUE);
        return 0;
 
    case WM_PAINT:
        hdc=BeginPaint(hwnd, &ps);
 
        cbparam.hdc=hdc;
        cbparam.xText=cbparam.xStart=cxChar;
        cbparam.yText=cbparam.yStart=cyChar;
        cbparam.xIncr=cxChar*MAXLEN;
        cbparam.yIncr=cyChar;
        cbparam.xMax=cbparam.xIncr*(1+cxClient/cbparam.xIncr);
        cbparam.yMax=cyChar*(cyClient/cyChar-1);
 
        GetString((PSTRCB) GetStrCallBack, (PVOID) &cbparam);
 
        EndPaint(hwnd, &ps);
        return 0;
 
    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, iMsg, wParam, lParam);
}
Всё это компилируется, запускается и работает, но то что расшарено через pragma на деле не расшарено и каждый новый экземпляр добавляет и удаляет только свои строки.
Петзолд пишет что нужно мол дать компоновщику понять что использоваться будут расшаренные ресурсы, но я так и не нашёл куда это приписать (метод тыка не помог). С кодом вроде всё ок и так, то что расшарено через pragma проинициализировано как и требуется чтобы оно было расшарено.

Может можно как-то задавать параметри для компоновщика в коде там в начале или ещё чего хитрое? Какая-то же возможность должна быть же ...

Добавлено через 8 минут
Хм, попробовал добавить
C
1
#pragma comment(linker, "/section:.CBTHook,rws") // даем права этой секции
теперь приложение при работе нескольких экземпляров то крашиться, то выводит непойми что ... что-то я напутал, сейчас надо бы найти ошибку, но тем не менее теперь видно что разные экземпляры точно видят друг друга чего я и добивался изначально в теме. Так что проблема компоновки решена, большое спасибо -=ЮрА=- за помощь.

Добавлено через 8 минут
Всё же что-то в примере не то, так как даже скопипастив код из книги приложение вылетает если работает несколько экземпляров, почему-то не удаётся у них делить память, хотя визуально вроде код в порядке .
-=ЮрА=-
Заблокирован
Автор FAQ
13.03.2012, 18:19     Задать параметр для компоновщика в VS #4
Цитата Сообщение от Gepar Посмотреть сообщение
.CBTHook,rws"
- CBTHook - имя т.е. если у тебя
Цитата Сообщение от Gepar Посмотреть сообщение
shared
то пиши вместо .CBTHook shared
Gepar
 Аватар для Gepar
1173 / 529 / 20
Регистрация: 01.07.2009
Сообщений: 3,512
13.03.2012, 18:22  [ТС]     Задать параметр для компоновщика в VS #5
-=ЮрА=-, ну это и так понятно, если что-то не правильно указать то vs предупреждает что мол
C++
1
#pragma comment(linker, "/section:.CBTHook,rws")
не имеет смысла так как до этой строчки не определено что такое .CBTHook. Но почему программа работает не корректно до конца не ясно ...
-=ЮрА=-
Заблокирован
Автор FAQ
13.03.2012, 18:25     Задать параметр для компоновщика в VS #6
Цитата Сообщение от Gepar Посмотреть сообщение
что такое .CBTHook.
- да говорю же имя зашареной секции)))

C
1
2
3
4
5
#pragma data_seg(".SHARED")    // секция в памяти общая для всех процессов
PSTR pszStrings[MAX_STRINGS]={NULL};
int iTotal=0;
#pragma data_seg()              // конец секции
#pragma comment(linker, "/section:.SHARED,rws") // даем права этой секции
-=ЮрА=-
Заблокирован
Автор FAQ
13.03.2012, 18:36     Задать параметр для компоновщика в VS #7
Вот код
C
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
// GeparDLL.cpp : Defines the entry point for the DLL application.
//
#include "stdafx.h"
#include "GeparDLL.h"
#define MAX_STRINGS 256
#define EXPORT __declspec(dllexport)
 
EXPORT BOOL CALLBACK AddString (PSTR);
EXPORT BOOL CALLBACK DeleteString (PSTR);
EXPORT int CALLBACK GetString (PSTR, PVOID);
 
#pragma data_seg(".GEPAR")    // ñåêöèÿ Гў ГЇГ*ìÿòè îáùГ*Гї äëÿ ГўГ±ГҐГµ ïðîöåññîâ
PSTR pszStrings[MAX_STRINGS]={NULL};
int iTotal=0;
#pragma data_seg()              // ГЄГ®Г*ГҐГ¶ ñåêöèè
#pragma comment(linker, "/section:.GEPAR,rws") // Г¤Г*ГҐГ¬ ГЇГ°Г*ГўГ* ýòîé ñåêöèè
 
int WINAPI DllMain(HINSTANCE hInstance, DWORD fdwReason, PVOID pvReserved)
{
        int i;
        switch(fdwReason)
        {
                //Nothing to do whe process (or thread) begins
 
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
                break;
 
        //When process terminates, free any remining blocks
        case DLL_PROCESS_DETACH:
                for(i=0; i<iTotal;i++)
                        UnmapViewOfFile(pszStrings[i]);
                break;
        }
 
        return TRUE;
}
 
EXPORT BOOL CALLBACK AddString(PSTR pStringIn)
{
        HANDLE hString;
        PSTR pString;
        int i, iLength, iCompare;
 
        if(iTotal==MAX_STRINGS-1)
                return FALSE;
 
        iLength=strlen(pStringIn);
        if(iLength==0)
                return FALSE;
 
        hString=CreateFileMapping((HANDLE) -1, NULL, PAGE_READWRITE, 0, 1+iLength, NULL);
        
        if(hString==NULL)
                return FALSE;
 
        pString=(PSTR) MapViewOfFile(hString, FILE_MAP_WRITE, 0, 0, 0);
        strcpy(pString, pStringIn);
        AnsiUpper(pString);
 
        for(i=iTotal; i>0; i--)
        {
                iCompare=strcmpi(pStringIn, pszStrings[i-1]);
 
                if(iCompare>=0)
                        break;
                
                pszStrings[i]=pszStrings[i-1];
        }
 
        pszStrings[i]=pString;
 
        iTotal++;
        return TRUE;
}
 
EXPORT BOOL CALLBACK DeleteString (PSTR pStringIn)
{
        int i, j, iCompare;
 
        if(0==strlen(pStringIn))
                return FALSE;
 
        for(i=0; i<iTotal; i++)
        {
                iCompare=lstrcmpi(pszStrings[i], pStringIn);
                
                if(iCompare==0)
                        break;
        }
 
        //If given string not in list, return without taking action
        if(i==iTotal)
                return FALSE;
 
        //Else free memory occupied by the string and adjust list donward
        UnmapViewOfFile(pszStrings[i]);
 
        for(j=i; i<iTotal;j++)
                pszStrings[j]=pszStrings[j+1];
 
        pszStrings[iTotal--]=NULL; //Destroy unused pointer
        return TRUE;
}
 
EXPORT int CALLBACK GetString (PSTR pfnGetStrCallBack, PVOID pParam)
{
        BOOL bReturn;
        int i;
 
        for(i=0;i<iTotal;i++)
        {
                bReturn = GetString(pszStrings[i], pParam);
 
                if(bReturn==FALSE)
                        return i+1;
        }
        return iTotal;
}
 
 
// This is an example of an exported variable
GEPARDLL_API int nGeparDLL=0;
 
// This is an example of an exported function.
GEPARDLL_API int fnGeparDLL(void)
{
    return 42;
}
 
// This is the constructor of a class that has been exported.
// see GeparDLL.h for the class definition
CGeparDLL::CGeparDLL()
{ 
    return; 
}
Проект прилагаю
Миниатюры
Задать параметр для компоновщика в VS  
Вложения
Тип файла: rar GeparDLL_proj.rar (9.4 Кб, 4 просмотров)
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.03.2012, 18:37     Задать параметр для компоновщика в VS
Еще ссылки по теме:

C++ Ошибка компоновщика: ссылка на неразрешенный внешний символ
C++ Общий параметр для всех классов и создание объекта по известному адресу
Как правильно задать параметр "время выполнения алгоритма"? C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
-=ЮрА=-
13.03.2012, 18:37     Задать параметр для компоновщика в VS
  #8

Не по теме:

Цитата Сообщение от -=ЮрА=- Посмотреть сообщение
CreateFileMapping((HANDLE) -1,
- а так разве можно???
Лично у меня код хоть из книги вызывает сильные претензии, что должен делать алгоритм???

Yandex
Объявления
13.03.2012, 18:37     Задать параметр для компоновщика в VS
Ответ Создать тему
Опции темы

Текущее время: 01:56. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru