반응형

Windows API(CreateFile)을 이용해 간단히 아두이노와 시리얼 통신을 할 수 있다.


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
char state;
 
void setup() {
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  Serial.begin(9600);
  Serial.println("Arduino ready.");
}
 
void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available())
  {
    state = Serial.read();
    while (Serial.available())
    {
      Serial.read();  // 첫 번째 문자만 입력받고 나머지는 버린다.
    }
    
    if (state == '0')
    {
      digitalWrite(LED_BUILTIN, LOW);
      Serial.println("LED OFF");
    } else
    {
      digitalWrite(LED_BUILTIN, HIGH);
      Serial.println("LED ON");
    }
  }
 
  delay(100);
}


위 소스를 컴파일 하고 아두이노에 업로드 한다. 시리얼 모니터를 통해서도 Builtin LED를 제어할 수 있다.


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
#ifndef SERIALCLASS_H_INCLUDED
#define SERIALCLASS_H_INCLUDED
 
#define ARDUINO_WAIT_TIME 2000
 
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
 
class Serial
{
private:
    //Serial comm handler
    HANDLE hSerial;
    //Connection status
    bool connected;
    //Get various information about the connection
    COMSTAT status;
    //Keep track of last error
    DWORD errors;
 
public:
    //Initialize Serial communication with the given COM port
    Serial(const char* portName);
    //Close the connection
    ~Serial();
    //Read data in a buffer, if nbChar is greater than the
    //maximum number of bytes available, it will return only the
    //bytes available. The function return -1 when nothing could
    //be read, the number of bytes actually read.
    int ReadData(char* buffer, unsigned int nbChar);
    //Writes data from a buffer through the Serial connection
    //return true on success.
    bool WriteData(const char* buffer, unsigned int nbChar);
    //Check if we are actually connected
    bool IsConnected();
 
 
};
 
#endif // SERIALCLASS_H_INCLUDED


Serial class header.


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
#include "SerialHeader.h"
 
Serial::Serial(const char* portName)
{
    //We're not yet connected
    this->connected = false;
 
    //Try to connect to the given port throuh CreateFile
    //CreateFile may need to be replaced with CreateFileA or...
    //Project - XXX Properties - Configuration Properties - Advanced - Character Set - Use Multi-Byte Character Set
    this->hSerial = CreateFileA(portName,
        GENERIC_READ | GENERIC_WRITE,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
 
    //Check if the connection was successfull
    if (this->hSerial == INVALID_HANDLE_VALUE)
    {
        //If not success full display an Error
        if (GetLastError() == ERROR_FILE_NOT_FOUND) {
 
            //Print Error if neccessary
            printf("ERROR: Handle was not attached. Reason: %s not available.\n", portName);
 
        }
        else
        {
            printf("ERROR!!!");
        }
    }
    else
    {
        //If connected we try to set the comm parameters
        DCB dcbSerialParams = { 0 };
 
        //Try to get the current
        if (!GetCommState(this->hSerial, &dcbSerialParams))
        {
            //If impossible, show an error
            printf("failed to get current serial parameters!");
        }
        else
        {
            //Define serial connection parameters for the arduino board
            dcbSerialParams.BaudRate = CBR_9600;
            dcbSerialParams.ByteSize = 8;
            dcbSerialParams.StopBits = ONESTOPBIT;
            dcbSerialParams.Parity = NOPARITY;
            //Setting the DTR to Control_Enable ensures that the Arduino is properly
            //reset upon establishing a connection
            dcbSerialParams.fDtrControl = DTR_CONTROL_ENABLE;
 
            //Set the parameters and check for their proper application
            if (!SetCommState(hSerial, &dcbSerialParams))
            {
                printf("ALERT: Could not set Serial Port parameters");
            }
            else
            {
                //If everything went fine we're connected
                this->connected = true;
                //Flush any remaining characters in the buffers 
                PurgeComm(this->hSerial, PURGE_RXCLEAR | PURGE_TXCLEAR);
                //We wait 2s as the arduino board will be reseting
                Sleep(ARDUINO_WAIT_TIME);
            }
        }
    }
 
}
 
Serial::~Serial()
{
    //Check if we are connected before trying to disconnect
    if (this->connected)
    {
        //We're no longer connected
        this->connected = false;
        //Close the serial handler
        CloseHandle(this->hSerial);
    }
}
 
int Serial::ReadData(char* buffer, unsigned int nbChar)
{
    //Number of bytes we'll have read
    DWORD bytesRead;
    //Number of bytes we'll really ask to read
    unsigned int toRead;
 
    //Use the ClearCommError function to get status info on the Serial port
    ClearCommError(this->hSerial, &this->errors, &this->status);
 
    //Check if there is something to read
    if (this->status.cbInQue > 0)
    {
        //If there is we check if there is enough data to read the required number
        //of characters, if not we'll read only the available characters to prevent
        //locking of the application.
        if (this->status.cbInQue > nbChar)
        {
            toRead = nbChar;
        }
        else
        {
            toRead = this->status.cbInQue;
        }
 
        //Try to read the require number of chars, and return the number of read bytes on success
        memset(buffer, 0, nbChar);
        if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL))
        {
            return bytesRead;
        }
 
    }
 
    //If nothing has been read, or that an error was detected return 0
    return 0;
 
}
 
 
bool Serial::WriteData(const char* buffer, unsigned int nbChar)
{
    DWORD bytesSend;
 
    //Try to write the buffer on the Serial port
    if (!WriteFile(this->hSerial, (void*)buffer, nbChar, &bytesSend, 0))
    {
        //In case it don't work get comm error and return false
        ClearCommError(this->hSerial, &this->errors, &this->status);
 
        return false;
    }
    else
        return true;
}
 
bool Serial::IsConnected()
{
    //Simply return the connection status
    return this->connected;
}


Serial class source.



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
#include <iostream>
#include "SerialHeader.h"
 
using namespace std;
 
int main()
{
    Serial* ser = new Serial("\\\\.\\COM3");
    char message[255];    
 
    if (ser->IsConnected()) {
        cout << "Serial Communication Connected." << endl;
        // memset(message, 0, sizeof(message));
        // Serial::ReadData() 내부에서 memset이 실행된다.
        ser->ReadData(message, sizeof(message));
        cout << "Message from Arduino: " << message << endl;
    } else {
        cout << "Device can not be found or can not be configured." << endl;
 
        return 0;
    }
    
    while (true) {
        cout << "0: Off, 1 : On, q(Q) : Quit" << endl << "Choose : ";        
        cin >> message;
 
        if (!strcmp(message, "q"|| !strcmp(message, "Q")) {
            break;
        } else if (!strcmp(message, "0")) {            
            ser->WriteData("0"1);
            Sleep(200); // 아두이노와의 시리얼 통신을 위한 대기 시간.            
            ser->ReadData(message, sizeof(message));
            cout << "Message from Arduino: " << message << endl;
        } else {
            ser->WriteData("1"1);
            Sleep(200); // 아두이노와의 시리얼 통신을 위한 대기 시간.            
            ser->ReadData(message, sizeof(message));
            cout << "Message from Arduino: " << message << endl;
        }
    }
 
    return 0;
}


Windows에서 위 소스를 실행하면 연결된 아두이노의 Builtin LED를 제어할 수 있다.


※ 참고: Arduino and C++ (for Windows)



반응형
Posted by J-sean
:
반응형

2021.09.25 - [C, C++] - Qt6 설치 및 간단한 사용법

2021/02/13 - [C, C++] - Linux(Ubuntu) Qt5 Image Display - 리눅스(우분투) Qt5 이미지 디스플레이

2021/02/12 - [C, C++] - Linux(Ubuntu) Qt5 GUI Programming - 리눅스(우분투) Qt5 GUI 프로그래밍

 

Qt는 GUI 프로그램 개발에 널리 쓰이는 크로스 플랫폼 프레임워크이다. 홈페이지에서 Open Source 버전을 다운 받아 실행 한다.

 

기본설정에서 MSVC 2017 64-bit만 추가한다.

 

Qt 설치가 완료되면 Visual Studio에서도 사용 할 수 있도록 Extension을 설치 한다.

 

Online에서 qt를 검색해 Qt Visual Studio Tools를 설치한다.

 

설치가 완료되면 Qt Options를 선택 한다.

 

 

Qt가 설치된 위치의 msvc2017_64 폴더를 Add 한다.

 

설치가 완료 되었으면 Qt Creator를 실행하고 Qt Widgets Application 프로젝트를 만들어 준다.

 

프로젝트 폴더 선택 외에는 기본값으로 진행 한다.

 

설정이 완료되면 아래와 같은 화면이 나온다.

 

 

Forms - Mainwindow.ui 디자인 화면에서 PushButton과 Label을 적당한 위치에 배치한다. Label은 기본 크기보다 약간 크게 늘려 준다.

Label의 Property에서 alignment - Horizontal을 AlignHCenter로 바꿔준다.

 

PushButton에서 오른쪽 클릭 - Go to slot... 을 선택한다.

 

QAbstractButton - clicked() 를 선택한다.

 

mainWindow.cpp 에 on_pushButton_clicked() 가 생성된다.

 

 

mainwindow.h 에 QMessageBox 헤더 파일을 include 하고 IsClicked, OriginalStatus, MsgBox 멤버 변수를 추가한다.

 

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
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
 
#include <QMainWindow>
#include <QMessageBox>
 
namespace Ui {
class MainWindow;
}
 
class MainWindow : public QMainWindow
{
    Q_OBJECT
 
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
 
private slots:
    void on_pushButton_clicked();
 
private:
    Ui::MainWindow *ui;
 
    bool IsClicked;
    QString OriginalStatus;
    QMessageBox MsgBox;
};
 
#endif // MAINWINDOW_H
cs

 

mainwindow.cpp 에서 constructor와 on_pushButton_clicked() 를 아래와 같이 수정해 준다.

 

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
#include "mainwindow.h"
#include "ui_mainwindow.h"
 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
 
    IsClicked = false;
    OriginalStatus = ui->pushButton->styleSheet();
    ui->label->setText("Unchanged");
    MsgBox.setWindowTitle("Sean");
    MsgBox.setText("Button Color Change");
    MsgBox.setInformativeText("Do you want to change button color?");
    MsgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
    MsgBox.setDefaultButton(QMessageBox::Yes);
}
 
MainWindow::~MainWindow()
{
    delete ui;
}
 
void MainWindow::on_pushButton_clicked()
{
    if (IsClicked == false)
    {
        int ret = MsgBox.exec();
 
        switch(ret)
        {
            case QMessageBox::Yes:
                ui->pushButton->setStyleSheet("color: blue;"
                                              "background-color: red;");
                ui->label->setText("Changed");
                IsClicked = !IsClicked;
                break;
 
            case QMessageBox::No:
                ui->label->setText("No");
                break;
 
            default:
                ui->label->setText("Cancel");
                break;
        }
    } else {
        IsClicked = !IsClicked;
        ui->pushButton->setStyleSheet(OriginalStatus);
        ui->label->setText("Unchanged");
    }
}
cs

 

 

빌드(Ctrl + B) 후 실행 (Ctrl + R) 한다.

 

PushButton을 클릭하면 MessageBox가 나온다.

 

Yes를 클릭하면 PushButton의 색과 Label 의 text가 변한다.

 

 

반응형
Posted by J-sean
:
반응형

JSON (JavaScript Object Notation)은 가벼운 data 교환 포멧이다. C++이 공식으로 지원하는 형식은 아니지만 분석에 사용 가능한 여러가지 라이브러리가 있다. 그 중 JsonCpp의 사용 방법이다.


홈페이지에서 소스를 다운 받고 압축을 풀면 아래와 같은 파일들이 나온다.


amalgamate.py를 실행한다.


dist라는 폴더에 소스파일과 헤더 파일이 생성된다.


makefiles - mscv2010 - jsoncpp.sln을 실행 한다.


Retarget Projects가 실행된다.


3개의 프로젝트가 나타난다.


각 프로젝트의 Property Pages - Configuration Properties - C/C++ - Code Generation - Runtime Library를 /MDd로 바꿔 준다.


Build 해 준다.


makefiles - msvc2010 - Debug 폴더에 lib_json.lib가 생성된다.


JsonCpp를 사용할 프로젝트를 만들고 Include Directory(jsoncpp-master\include)와 Library Directory(jsoncpp-master\makefiles\msvc2010\Debug)를 추가해 준다.




쓰기 예제

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
#pragma comment (lib, "lib_json.lib")
 
#include <iostream>
#include <fstream>
#include "json/json.h"
 
using namespace std;
using namespace Json;
 
int main()
{
    ofstream json_file;
    json_file.open("JSON_DATA.json");
 
    Value Computer;
    Computer["CPU"= "I7";
    Computer["RAM"= "16G";
 
    Value Language;
    Language["C++"= "Visual Studio";
    Language["Python"= "IDLE";
    
    Computer["Program"= Language;
    Computer["HDD"= "2TB";
 
    Value Cable;
    Cable.append("Power");
    Cable.append("Printer");
    Cable.append("Mouse");
 
    Computer["Computer"]["Cable"= Cable;
 
    Value number;
    number["Int"= 123;
    number["Double"= 456.012;
    number["Bool"= true;
 
    Computer["Computer"]["Number"= number;
 
    StreamWriterBuilder builder;
    builder["commentStyle"= "None";
    builder["indentation"= "    ";  // Tab
    unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());
 
    // 알파벳 순으로 write 된다.
    writer->write(Computer, &cout);
    writer->write(Computer, &json_file);
    cout << endl;  // add lf and flush
 
    json_file.close();
 
    return 0;
}
cs


아래와 같은 결과가 출력 된다.


같은 결과의 JSON_DATA.json 파일이 생성 된다.

읽기 예제

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
#pragma comment (lib, "lib_json.lib")
 
#include <iostream>
#include <fstream>
#include "json/json.h"
 
using namespace std;
using namespace Json;
 
int main()
{
    ifstream json_dir("JSON_DATA.json");
    CharReaderBuilder builder;
    builder["collectComments"= false;
    Value value;
 
    JSONCPP_STRING errs;
    bool ok = parseFromStream(builder, json_dir, &value, &errs);
 
    if (ok == true)
    {
        cout << "CPU: " << value["CPU"<< endl;
        cout << "Program Python: " << value["Program"]["Python"<< endl;
        cout << "Computer Cable: " << value["Computer"]["Cable"<< endl;
        cout << "Computer Cable[0]: " << value["Computer"]["Cable"][0<< endl;
        cout << endl;
 
        cout << "Computer Number Int(as int): " << value["Computer"]["Number"].get("Int"-1).asInt() << endl;
        // "Int" 값이 없으면 -1 반환.
        cout << "Computer Number Int(as int): " << value["Computer"]["Number"]["Int"].asInt() << endl;
        // "Int" 값이 없으면 0 반환.
        cout << "Computer Number Double(as double): " << value["Computer"]["Number"].get("Double"-1).asDouble() << endl;
        // "Double" 값이 없으면 -1 반환.
        cout << "Computer Number Double(as string): " << value["Computer"]["Number"].get("Double""Empty").asString() << endl;
        // "Double" 값이 없으면 Empty 반환.
        cout << "Computer Number Bool(as bool): " << value["Computer"]["Number"].get("Bool"false).asBool() << endl;
        // "Bool" 값이 없으면 false 반환.
        cout << endl;
 
        cout << "Root size: " << value.size() << endl;
        cout << "Program size: " << value["Program"].size() << endl;
        cout << "Computer Cable size: " << value["Computer"]["Cable"].size() << endl;
        cout << endl;
 
        int size = value["Computer"]["Cable"].size();
        // size() 값을 for 문에서 그대로 비교하면 warning C4018가 발생 한다.
        for (int i = 0; i < size; i++)
            cout << "Computer Cable: " << value["Computer"]["Cable"][i] << endl;
        cout << endl;
 
        for (auto i : value["Computer"]["Cable"])
            cout << "Computer Cable: " << i << endl;
    }
    else
    {
        cout << "Parse failed." << endl;
    }
 
    return 0;
}
cs


아래와 같은 결과가 출력 된다.



반응형

'C, C++' 카테고리의 다른 글

Qt 스프라이트 애니매이션  (0) 2019.02.21
Qt 설치 및 간단한 사용 예  (4) 2019.01.16
Console 어플리케이션에 이미지 디스플레이 하기  (0) 2018.11.22
Python C API  (0) 2018.11.21
MySQL C API  (0) 2018.11.20
Posted by J-sean
:
반응형

Windows에서 Visual Studio를 이용해 Linux에 원격으로 접속해서 C++ 프로그램 개발이 가능하다.

Linux에는 미리 gcc나 g++가 설치 되어 있어야 한다.

- Fedora: sudo dnf install g++

- Ubuntu: sudo apt-get install g++


New Project 창을 열고 Visual C++ - Cross Platform - Linux - 원하는 프로젝트를 선택해서 이름과 디렉토리를 지정해 준다.


간단한 소스가 입력된 프로젝트가 생성 된다. 아직 Linux에 연결되지는 않았다.


ifconfig 명령으로 접속할 Linux system의 주소를 확인한다.




Tools - Options창에서 Cross Platform - Add를 클릭한다.


Host name, Port, User name, Authentication type, Password를 입력한다.


헤더 파일, 인텔리센스등의 업데이트가 진행 된다.


업데이트가 완료되면 연결된 Linux system의 정보가 등록 된다.


Build 하면 Source를 Linux system으로 복사하고 Remote Build가 진행 된다.


Linux system에서 확인해 보면 실행파일이 생성 되어 있고 문제 없이 실행 된다.


Property Pages에서 Output Directory, Remote Build Machine등 여러가지 설정을 바꿀 수 있다.


반응형
Posted by J-sean
:
반응형

Console에 이미지를 디스플레이 하는 간단한 코드.

윈도우 어플리케이션처럼 이미지가 지워졌을때 다시 그려주는 코드가 없기 때문에 커서 이동, 마우스 클릭등으로 이미지가 지워져도 다시 그려주지는 않는다.


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
#include<stdio.h>
#include<Windows.h>
 
int main(void)
{
    printf("Image loading...\n");
    Sleep(100); // 콘솔이 나타날때까지 잠시 멈추지 않으면 이미지가 표시되지 않는 경우가 생긴다.
 
    HWND hWnd = GetConsoleWindow();
    // Retrieves the window handle used by the console associated with the calling process.
 
    HBITMAP hImage, hOldBitmap;
 
    HDC hDC = GetDC(hWnd);
    HDC hMemDC = CreateCompatibleDC(hDC);
 
    hImage = (HBITMAP)LoadImage(NULL, TEXT("cat.bmp"), IMAGE_BITMAP, 00, LR_LOADFROMFILE | LR_CREATEDIBSECTION);
    // Loads an icon, cursor, animated cursor, or bitmap.
 
    hOldBitmap = (HBITMAP)SelectObject(hMemDC, hImage);
    BitBlt(hDC, 505050 + 61250 + 409, hMemDC, 00, SRCCOPY); // Image(612, 409) at (50, 50)
    // The BitBlt function performs a bit-block transfer of the color data corresponding to a rectangle of pixels
    // from the specified source device context into a destination device context.
 
    SelectObject(hMemDC, hOldBitmap);
    DeleteObject(hImage);
    DeleteDC(hMemDC);
    ReleaseDC(hWnd, hDC);
 
    return 0;
}
cs


결과:






반응형

'C, C++' 카테고리의 다른 글

Qt 스프라이트 애니매이션  (0) 2019.02.21
Qt 설치 및 간단한 사용 예  (4) 2019.01.16
How to install and use JsonCpp - JsonCpp 설치 및 사용  (2) 2019.01.08
Python C API  (0) 2018.11.21
MySQL C API  (0) 2018.11.20
Posted by J-sean
:

Python C API

C, C++ 2018. 11. 21. 15:52 |
반응형

가장 간단하게 Python을 C에 embed 시키는 방법은 Very High Level interface를 사용 하는 것이다. VHL interface는 어플리케이션과 직접적인 상관 없이 Python script를 실행하기 위한 것이다.

 

관련 문서

Python/C API Reference Manual

 

우선 Python C API 관련 Include, Library 디렉토리를 프로젝트에 추가한다.

C:\Users\UserName\AppData\Local\Programs\Python\PythonXXX\include

C:\Users\UserName\AppData\Local\Programs\Python\PythonXXX\libs

 

파이썬 공식 홈페이지에서 다운 받은 파이썬 인스톨러 패키지를 설치 했다면 Solution Configurations를 Release로 설정 한다. Debug 모드로 build 할 경우 pythonXX_d.lib를 찾을 수 없다는 에러가 발생한다. pythonXX_d.lib 파일을 생성하려면 파이썬 소스를 받아서 직접 컴파일해야 한다.

 

예제:

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
#pragma comment(lib, "python36.lib")
#include <Python.h>
 
int main(int argc, char *argv[])
{
    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
    // Decode a byte string from the locale encoding with the surrogateescape error handler:
    // undecodable bytes are decoded as characters in range U+DC80..U+DCFF. If a byte sequence
    // can be decoded as a surrogate character, escape the bytes using the surrogateescape error
    // handler instead of decoding them.
    // Return a pointer to a newly allocated wide character string, use PyMem_RawFree() to free
    // the memory. If size is not NULL, write the number of wide characters excluding the null
    // character into *size
    if (program == NULL) {
        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
        exit(1);
    }
    Py_SetProgramName(program);  /* optional but recommended */
    // This function should be called before Py_Initialize() is called for the first time, if it
    // is called at all.It tells the interpreter the value of the argv[0] argument to the main()
    // function of the program(converted to wide characters).This is used by Py_GetPath() and some
    // other functions below to find the Python run - time libraries relative to the interpreter
    // executable.
 
    Py_Initialize();
    // Initialize the Python interpreter. In an application embedding Python, this should be called
    // before using any other Python/C API functions
    if (Py_IsInitialized())
    // Return true (nonzero) when the Python interpreter has been initialized, false (zero) if not.
    // After Py_FinalizeEx() is called, this returns false until Py_Initialize() is called again.
    {
        PyRun_SimpleString("print('Hello Python')");
        // This is a simplified interface to PyRun_SimpleStringFlags(), leaving the PyCompilerFlags*
        // argument set to NULL.
        PyRun_SimpleString("from time import time, ctime\n"
            "print('Today is', ctime(time()))\n");
        //PyRun_SimpleString("from time import time, ctime\nprint('Today is', ctime(time()))\n");
 
        if (Py_FinalizeEx() < 0)
        // Undo all initializations made by Py_Initialize() and subsequent use of Python/C API
        // functions, and destroy all sub-interpreters that were created and not yet destroyed
        // since the last call to Py_Initialize().
        {
            exit(120);
        }
        PyMem_RawFree(program);
        // Frees the memory block pointed to by p, which must have been returned by a previous call
        // to PyMem_RawMalloc(), PyMem_RawRealloc() or PyMem_RawCalloc().
        // Otherwise, or if PyMem_RawFree(p) has been called before, undefined behavior occurs.
        // If p is NULL, no operation is performed.
    }
 
    return 0;
}
cs

 

반응형
Posted by J-sean
:

MySQL C API

C, C++ 2018. 11. 20. 11:31 |
반응형

MySQL C API 는 C 프로그램이 MySQL 데이터 베이스 내용에 접근 할 수 있도록 MySQL 서버/클라이언트 프로토콜의 저수준 접근을 제공 한다.

 

5.7 버전 참고 문서: MySQL C API

 

설정:

  • 버전 설정: X64

  • Project - XXX Properties... - Configuration Properties - C/C++ - General - Additional Include Directories - C:\Program Files\MySQL\MySQL Server 5.7\include 추가
  • Project - XXX Properties... - Configuration Properties - Linker - General - Additional Library Directories - C:\Program Files\MySQL\MySQL Server 5.7\lib 추가

 

 

  • Project - XXX Properties... - Configuration Properties - Linker - Input - Additional Dependencies - libmysql.lib 추가 하거나 소스에 아래 코드 추가
    #pragma comment (lib, "libmySQL.lib")
  • 실행파일 폴더에 libmysql.dll 복사

 

예제:

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
#include <my_global.h>
#include <mysql.h>
 
#pragma comment (lib, "libmySQL.lib")
 
int main()
{
    MYSQL mysql;            // MySQL 정보를 담을 구조체
    MYSQL* mysqlPtr = NULL;    // MySQL connection 핸들러
    MYSQL_RES* Result = NULL;        // 쿼리 성공시 결과를 담는 구조체 포인터
    MYSQL_ROW Row;            // 쿼리 성공시 결과로 나온 행의 정보를 담는 구조체
    int stat;                // 쿼리 요청 후 결과
 
    printf("MySQL Client Version: %s\n\n", mysql_get_client_info());
    // Returns client version information as a string
 
    mysql_init(&mysql); // Gets or initializes a MYSQL structure 
 
    mysqlPtr = mysql_real_connect(&mysql, "127.0.0.1""root""1234""shopdb"3306, (char*)NULL0);
    // Connects to a MySQL server
 
    if (mysqlPtr == NULL)
    {
        printf("MySQL connection error: %s\n", mysql_error(&mysql));
        // Returns the error message for the most recently invoked MySQL function
        return 1;
    }
 
    // MySQL에서 사용하는 문자세트를 Visual Studio가 사용하는 euc-kr로 바꾸기
    mysql_query(mysqlPtr, "set session character_set_connection=euckr");
    mysql_query(mysqlPtr, "set session character_set_results=euckr");
    mysql_query(mysqlPtr, "set session character_set_client=euckr");
 
    const char* Query = "SELECT * FROM memberTBL";
    stat = mysql_query(mysqlPtr, Query);    // Executes an SQLquery specified as a null-terminated string
    if (stat != 0)
    {
        printf("MySQL connection error: %s\n", mysql_error(&mysql));
        return 1;
    }
 
    Result = mysql_store_result(mysqlPtr);    // Retrieves a complete result set to the client
    while ((Row = mysql_fetch_row(Result)) != NULL)    // Fetches the next row from the result set 
    {
        printf("%s %s %s\n", Row[0], Row[1], Row[2]);
    }
 
    mysql_free_result(Result);    // Frees memory used by a result set
    mysql_close(mysqlPtr);    // Closes a server connection
 
    return 0;
}
cs

5.7 버전의 MySQL은 빌드하면 C2011('struct' type redefinition) 에러가 발생하는 경우가 있다.

C2011 에러가 발생 하면 my_global.h 파일에 #define HAVE_STRUCT_TIMESPEC 코드를 추가해 준다.

 

 

반응형
Posted by J-sean
: