C++. How use SQLite in Windows Forms

В свое время знакомство с движком SQLite ограничилось разработками консольных приложений. Но вот настало время и более интересному использованию: интеграция в проекты сопряженных с созданием UI с помощью Windows Forms. Как и ранее я буду работать со средой разработки Microsoft Visual C++ 2008 Express Edition.
В отличии от консольных приложений все попытки связать SQLite с такого рода проектами были безуспешными. Может конечно у Вас получится, буду очень благодарен за письмо в мой адрес с Вашим рецептом. Приготовить по рецепту с официального сайта (The SQLite Amalgamation) также не удалось.

Из логов компилятора:
  • Command line error D8045 : cannot compile C file '.\sqlite3.c' with the /clr option
  • error LNK2019: unresolved external symbol _sqlite3_exec referenced in function _main
  • error LNK2019: unresolved external symbol _sqlite3_open referenced in function _main
Вопрос - почему? Причем этот вопрос судя по результатам поиска в "инете" не единичный. Как выяснилось чуть погодя проблема была связана с тем, что по сути своей Windows Forms является частью Microsoft .NET Framework. Внутри которой Windows Forms реализуется в рамках пространства имён System.Windows.Forms. В связи с этими нюансами и просходили всякие неприятности на моей кухне. И под конец на глаза попалась книжечка Using SQLite. Jay A. Kreibich, где сказано:


Building


There are a number of different ways to build SQLite, depending on what you’re trying


to build and where you would like it installed. If you are trying to integrate the SQLite

core into a host application, the easiest way to do that is to simply copy


sqlite3.c and


sqlite3.h
 

into your application’s source directory. If you’re using an IDE, the sqlite3.c


file can simply be added to your application’s project file and configured with the proper

search paths and build directives. If you want to build a custom version of the SQLite

library or


sqlite3 utility, it is also easy to do that by hand.


All of the SQLite source is written in C. It cannot be compiled by a C++ compiler. If

you’re getting errors related to structure definitions, chances are you’re using a C++

compiler.


Вопрос был снят. Получается, что нужно адаптировать SQLite библиотеку под .NET Framework. Для этого на официальном сайте есть ссылка на так называемый ADO.NET adapter for SQLite - System.Data.SQLite. 

Среди этих ресурсов (например - здесь) можно встретить вот такой ролик, который демонстирует сие адаптер - так сказать - in action. 

 

P.S.: For a CLR/.NET/WinForms projects you should use System.Data.SQLite.
Всем удачи :)

 

C/C++. Обращение к глобальным и локальным переменным

Не буду многословен. Для прямого обращения к глобальной переменной можно воспользоваться оператором расширения области видимости переменной variable:

::variable;

Соотвественно, для локальной переменной - по адресу.

some_function(&variable);

Ниже приведен примерчик для нагядности слов :)

#include <iostream>
using namespace std;
// Глобальная инициализация
// Глобальная переменная
int n = 100;
void glob() {
 ::n++;
}
void loc(int *n) {
 (*n)++;
}
int main() {
 // Локальная инициализация
 char temp;
 // Локальная переменная
 int n = 16;

 // ...до изменения переменных
 cout << "Global var before: n = " << ::n << "\n";
 cout << "Local var before: n = " << n << "\n";

 // Обращаемся к глобальной переменной и меняем ее
 glob();
 // Обращаемся к локальной переменной и также меняем ее
 loc(&n);
 // ...после изменения переменных
 cout << "Global var after: n = " << ::n << "\n";
 cout << "Local var after: n = " << n << "\n";
 // задержка...
 cin >> temp;
}

В итоге имеем:
 
Ура, все работает.

C++/CLI. Write to buffer (change cout on char buffer) and get string data from char buffer

Работая над проектом возникла необходимость в перехвате (громко сказано) стандартного вывода ( printf() ) для анализа того, с чем же приходилось работать. Далеко не копая, воспользовался "C"-шной функцией - sprintf(). Здесь небольшой faq. Данная функция на выходе все кладет в буфер. Приведу примерчик:

#include <stdio.h>

int main( void )
{
   char  buffer[200];
   int   j;
   


   /* Format and print various data: */
   j  = sprintf( buffer,     "   First string\n");
   j += sprintf( buffer + j, "   Second string\n");
   

   printf( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}

 

 

 

 
В итоге имеем:

Output:

First string

Second string

character count = 25

 

 

 

 
 То, что нужно. Далее снова появилась мини-задачка: буфер - он и в Африке буфер, мне нужны были содержащиеся в нем данные, в частности - все "пойманные" строки. Их нужно было извлечь. Так как проект разрабатывался с помощью Microsoft Visual C++ 9.0 Express Edition (этого было достаточно :) ), то для сие нужды воспользовался методом gcnew String() (в следствие C++/CLI).
Он нужен для convert from 'char *' to 'System::String ^' . И снова пример:

// some code

char buffer[16];
String ^str;

sprintf(buffer, "Testing...\0");
   
str = gcnew String(buffer);
this->textBox1->AppendText(str);

// some code

И о чудо, я вновь "вижу" :)
Кстати, скоро новый год, еще  21 день. Заранее всех с наступающим :)

JavaScript. Несложное создание гистограмм

Учитывая, что сейчас многие пользуются блого-сервисами (blogger, tumblr, livejournal, etc.), могут возникнуть потребности в создании гистограмм. Мы же любим, когда данные можно "потрогать". Использование PHP в этом случае затруднено. Поэтому самый простой способ - создание гистограмм на JavaScripte с помощью CSS-стилей. Сразу отмечу, что сие способ описан в руководстве Флэнагана по JavaScript (со своими изменениями).
Основную работу будет выполнять js-файл - BarChart.js (см. листинг ниже). На входе он ожидает данные в виде массива, значения которого он аккуратно заклыдывает в гистограмму, которую выдает на выходе. Все очень просто. Ниже представлен один из примеров гистаграммы (Test chart).
Получаемые гистограммы легко инсталлируются в веб-странички. При этом можно входные данные сделать динамичными, так сказать - поставить на поток, что должно сделать динамичным и саму гистограмму. Ниже представлены листинги индексной html-странички и BarChart.js.
 
index.html
 
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<!-- Без объявления DOCTYPE в IE рисунок будет выглядеть неправильно -->
<html>
<head>
<script src="BarChart.js"></script> <!-- Подключить библиотеку -->
<script>
function drawChart() {
var data = [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,50,50,50,5,5,5,5,5,5,5,5,50,6,6,7,7,7,60,8];
var chart = makeBarChart(data, 300, 300);
var container = document.getElementById("chartContainer");
container.appendChild(chart);
}
</script>
</head>
<body onload="drawChart( )">
<h2>Test chart</h2><!-- Заголовок гистограммы -->
<div id="chartContainer"><!-- Здесь рисуется гистограмма --></div>
<!-- Подпись под гистограммой -->
<i>Test chart</i>
</body>
</html>
 
BarChart.js
 
 /**
* BarChart.js:
* В этом файле содержится определение функции makeBarChart(), которая
* создает гистограмму для вывода содержимого массива data[].
* Общий размер гистограммы определяется необязательными аргументами
* width и height, которые учитывают пространство, необходимое для рамок
* гистограммы и внутренних отступов. Необязательный аргумент barcolor
* определяет цвет столбиков. Функция возвращает созданный ею элемент
* <div>, таким образом, вызывающий сценарий может манипулировать
* этим элементом, например, изменять величину отступов. Вызывающий
* сценарий должен вставить в документ полученный от функции элемент,
* чтобы сделать его видимым.
**/
function makeBarChart(data, width, height, barcolor) {
 // Предусмотреть значения по умолчанию для необязательных аргументов
 if (!width) width = 500;
 if (!height) height = 350;
 if (!barcolor) barcolor = "blue";
 // Аргументы width и height определяют общий размер гистограммы.
 // Чтобы получить размер создаваемого элемента, необходимо вычесть
 // из этих значений толщину рамок и величину отступов.
 width -= 24; // Вычесть 10px отступа и 2px толщины рамки слева и справа
 height -= 14; // Вычесть 10px отступа сверху и 2px толщины рамки сверху и снизу
 // Создать элемент для размещения гистограммы. Обратите внимание:
 // гистограмма позиционируется в относительных координатах, т. е.
 // в ней могут располагаться дочерние элементы с абсолютным
 // позиционированием, и отображаться при этом в нормальном потоке
 // вывода элементов документа.
 var chart = document.createElement("div");
 chart.style.position = "relative"; // Относительное позиционирование
 chart.style.width = width + "px"; // Ширина гистограммы
 chart.style.height = height + "px"; // Высота гистограммы
 chart.style.border = "solid black 1px"; // Определить рамку
 chart.style.paddingLeft = "10px"; // Добавить отступ слева
 chart.style.paddingRight = "10px"; // Справа
 chart.style.paddingTop = "10px"; // Сверху
 chart.style.paddingBottom = "0px"; // Но не снизу
 chart.style.backgroundColor = "white"; // Фон гистограммы - белый
 // Рассчитать ширину каждого столбика

 //var barwidth = Math.floor(width/data.length);
 var barwidth = 1;

 // Отыскать наибольшее число в массиве data[]. Обратите внимание
 // на грамотное использование функции Function.apply().
 var maxdata = Math.max.apply(this, data);
 // Масштабирующий множитель: scale*data[i] дает высоту столбика
 var scale = height/maxdata;
 // Обойти в цикле массив с данными и создать столбики для всех элементов
 for(var i = 0; i < data.length; i++) {
  var bar = document.createElement("div"); // Создать столбик
  var barheight = data[i] * scale; // Рассчитать высоту
  bar.style.position = "absolute"; // Уст. размер и положение
  bar.style.left = (barwidth*i+1+10)+"px"; // Добавить рамку столбика
  // и отступ
  bar.style.top = height-barheight+10+"px";// Добавить отступ
  // гистограммы
  bar.style.width = (barwidth-2) + "px"; // -2 - рамка столбика
  bar.style.height = (barheight-1) + "px"; // -1 - рамка сверху
  if (data[i] >= 50) bar.style.border = "solid red 1px"; // Стиль рамки столбика при значениях более 50
  if (data[i] < 50) bar.style.border = "solid blue 1px"; // Стиль рамки столбика при значениях менее 50
  bar.style.backgroundColor = barcolor; // Цвет столбика
  bar.style.fontSize = "0px"; // Учесть особенность IE
  chart.appendChild(bar); // Добавить столбик
  // в гистограмму
 }
 // В заключение вернуть элемент с гистограммой
 return chart;
}


Все представленные листинги можно скачать здесь. Всем удачи.