Getting results from a third party DLL in C++ - c++

I am very new to software programming.I have been working on a C++ project (using Code::Blocks) and trying to get results from a third party DLL written with Visual C++ 2010. So far I am able to load the DLL using LoadLibrary() and get the function address using GetProcAddress(). But I am not sure how I can proceed further to get some meaningful results. Information from the third party DLL manual is not very clear, at least to me. I would be much appreciated, if someone can point me to the right direction, please.
DLL information:
Calcdll.dll exports function StartJob.
StartJob, that accepts three parameters
double aInputData[NINPUTDATA], specifies input data
VARIANT aResData[NRESDATA], contains calculation results
VARIANT aOptions[NOPTIONSDATA], specifies optional flags (for future use)
NINPUTDATA: 100
NRESDATA: 100
NOPTIONSDATA 1
Usage from C++
// Calcdlld.h is located in the installation directory together
// with calcwin.dll and calcwin.lib
#include “calcdlld.h”
void CCalcdllsvrView::OnCalcolo()
{
// TODO: Add your control notification handler code here
VARIANT aRis[NRESDATA];
double aInp[NINPUTDATA];
double aOpt[NOPTIONSDATA];
// Collect data from input mask
GetData(vInp);
// Check for errors
if (!StartJob(aInp, aRis, aOpt))
return;
// Show results
ShowResults(aRis);
}
/*
Link Calcdll.lib together with your files.
Warning: positions 14,15 and 30 of the output array contain BSTR values, so in order to convert them to CString (in
Visual C++) is possible to create an instance of the class CString passing aRis[n].bstrVal to the constructor (see
VARIANT structure declaration):
*/
CString coilDescription (aRis[29].bstrVal);
AfxMessageBox(CString(“Coil type: “) + coilDescription);
//Contents of calcdlld.h
#define NINPUTDATA 100
#define NOPTIONSDATA 1
#define NRESDATA 100
extern "C" BOOL FAR PASCAL EXPORT StartJob(double vInp[NINPUTDATA], VARIANT vRis[NRESDATA], double vOpt[NOPTIONSDATA]);
My code
#include <iostream>
#include <string>
#include <cmath>
using namespace std;
#include <windows.h>
int main() {
double vInp[100];
VARIANT vRis[100];
double vOpt[1];
for (int i = 0; i < 100; i++ ) {
vInp[i] = 0;
}
//vInp[] = ;
vInp[0] = 2;
vInp[1] = 25;
vInp[8] = 1;
vInp[9] = 45;
vInp[14] = 2;
vInp[15] = 48;
vInp[16] = 2;
vInp[17] = 16;
vInp[18] = 11250;
vInp[26] = 45;
vInp[28] = 2.41627;
vInp[40] = 1;
vInp[45] = 1;
vInp[50] = 14;
vInp[51] = 2.2;
vInp[60] = 1;
vInp[61] = 0.11;
vInp[62] = 0.35;
vInp[63] = 203;
vInp[77] = 2;
cout << "vInp" << endl;
for (int i = 0; i < 100; i++ ) {
cout << i << ": " << vInp[i] << endl;
}
cout << "Start!" << endl;
typedef int (__stdcall *f_StartJob)(double vInp[100], VARIANT vRis[100], double vOpt[1]);
HINSTANCE hGetProcIDDLL = LoadLibrary("C:\\......\\calcdll.dll");
if (!hGetProcIDDLL) {
cout << "could not load the dynamic library" << endl;
return EXIT_FAILURE;
} else {
cout << "DLL loaded!" << endl << endl;
}
// resolve function address here
f_StartJob StartJob = (f_StartJob)GetProcAddress(hGetProcIDDLL, "StartJob");
if (!StartJob) {
cout << "could not locate the function" << endl;
return EXIT_FAILURE;
}
cout << "StartJob() returned " << StartJob(vInp, vRis, vOpt) << endl;
cout << vRis << endl;
return EXIT_SUCCESS;
}
Many thanks in advance!

Related

How to use CRT batch technique in Microsoft SEAL 3.1?

Can you please tell me whether SEAL 3.1 supports PolyCRTBuilder class? I am trying to run the following program but failed because the class is not declared in this scope.
/**
Suppose I have two arrays x = [1,2,3,4,5] and xMean = [3,3,3,3,3]. I composed and encrypted the two array using PolyCRTBuilder ( xCiphertext and xMeanCiphertext ) . If I subtract the two ciphertexts ( xCiphertext MINUS xMeanCiphertext ), I should get xResult = [-2, -1, 0, 1, 2] but after the homomorphic subtraction I am getting xResultDecrypted = [40959, 40960, 0 ,1, 2] . I can relate the overflow result to the plain modulus set but is there a work around for this problem. Here is the code:
*/
#include <iostream>
#include "seal/seal.h"
using namespace std;
using namespace seal;
/*
Helper function: Prints the parameters in a SEALContext.
*/
void print_parameters(shared_ptr<SEALContext> context)
{
// Verify parameters
if (!context)
{
throw invalid_argument("context is not set");
}
auto &context_data = *context->context_data();
/*
Which scheme are we using?
*/
string scheme_name;
switch (context_data.parms().scheme())
{
case scheme_type::BFV:scheme_name = "BFV";
break;
case scheme_type::CKKS:scheme_name = "CKKS";
break;
default:
throw invalid_argument("unsupported scheme");
}
cout << "/ Encryption parameters:" << endl;
cout << "| scheme: " << scheme_name << endl;
cout << "| poly_modulus_degree: " << context_data.parms().poly_modulus_degree() << endl;
/*
Print the size of the true (product) coefficient modulus.
*/
cout << "| coeff_modulus size: " << context_data.
total_coeff_modulus_bit_count() << " bits" << endl;
/*
For the BFV scheme print the plain_modulus parameter.
*/
if (context_data.parms().scheme() == scheme_type::BFV)
{
cout << "| plain_modulus: " << context_data.
parms().plain_modulus().value() << endl;
}
cout << "\\ noise_standard_deviation: " << context_data.
parms().noise_standard_deviation() << endl;
cout << endl;
}
int main(){
cout << "\nTotal memory allocated from the current memory pool: "<< (MemoryManager::GetPool().alloc_byte_count() >> 20) << " MB" << endl;
EncryptionParameters parms(scheme_type::BFV);
//EncryptionParameters parms;
parms.set_poly_modulus_degree(4096);
parms.set_coeff_modulus(coeff_modulus_128(4096));
parms.set_plain_modulus(40961); ////Make the coefficient modulus prime>2n to enable CRT batching
auto context = SEALContext::Create(parms);
print_parameters(context);
IntegerEncoder encoder(parms.plain_modulus());
KeyGenerator keygen(context);
PublicKey public_key = keygen.public_key();
SecretKey secret_key = keygen.secret_key();
// SEALContext context(parms);
// KeyGenerator keygen(context);
// auto public_key = keygen.public_key();
// auto secret_key = keygen.secret_key();
Encryptor encryptor(context, public_key);
Evaluator evaluator(context);
Decryptor decryptor(context, secret_key);
PolyCRTBuilder crtbuilder(context);
int slot_count = crtbuilder.slot_count();
int row_size = slot_count / 2;
vector<uint64_t> x_pod_matrix(slot_count, 0);
x_pod_matrix[0] = 1;
x_pod_matrix[1] = 2;
x_pod_matrix[2] = 3;
x_pod_matrix[3] = 4;
x_pod_matrix[4] = 5;
Plaintext x_plain_matrix;
crtbuilder.compose(x_pod_matrix, x_plain_matrix);
Ciphertext x_encrypted_matrix;
encryptor.encrypt(x_plain_matrix, x_encrypted_matrix);
vector<uint64_t> x_mean_pod_matrix(slot_count, 0);
x_mean_pod_matrix[0] = 3;
x_mean_pod_matrix[1] = 3;
x_mean_pod_matrix[2] = 3;
x_mean_pod_matrix[3] = 3;
x_mean_pod_matrix[4] = 3;
Plaintext x_mean_plain_matrix;
crtbuilder.compose(x_mean_pod_matrix, x_mean_plain_matrix);
Ciphertext x_mean_encrypted_matrix;
encryptor.encrypt(x_mean_plain_matrix, x_mean_encrypted_matrix);
evaluator.sub_plain(x_encrypted_matrix, x_mean_encrypted_matrix);
// Decrypt x_encrypted_matrix
Plaintext x_plain_result;
decryptor.decrypt(x_encrypted_matrix, x_plain_result);
vector<uint64_t> pod_result;
crtbuilder.decompose(x_plain_result, pod_result);
for(int i = 0; i < 5; i++) {
std::cout << pod_result[i] << '\n';
}
return 0;
}
PolyCRTBuilder has been renamed to BatchEncoder. Take a look at the src/examples directory in SEAL v3.1 (or native/examples in a newer version) and you'll see plenty of examples.
Kind of related to your question: the coeff_modulus_128 function hasn't existed in SEAL for quite a while; the same functionality is provided by the CoeffModulus::BFVDefault function. With these changes your code might work in SEAL 3.5 even.

Why won't this loop load the proper event?

Here is the code I wrote, and it runs fine, but it doesn't seem to actually load the events ... instead, it seems to fill the histograms and the cout with one arbitrary miniscule number.
include "TTree.h"
include "TFile.h"
include "TRandom.h"
include "TTree.h"
include "TCanvas.h"
include "TStyle.h"
include <iostream>
include "TH1.h"
include "TChain.h"
using namespace std;
void readtestsimple(){
TFile *file = TFile::Open("/file/");
TTree* comp_tree = (TTree*)file->Get("_compress_tree");
TChain* compchain = new TChain("_compress_tree");
compchain->Add("/file/");
TH1D *comp = new TH1D("comp","_compression",100,0,0.05);
Double_t _compression, _compressionU, _compressionV, _compressionY, _ch_compression;
Int_t _ch;
comp_tree->SetBranchAddress("_compression",&_compression);
comp_tree->SetBranchAddress("_compressionU",&_compressionU);
comp_tree->SetBranchAddress("_compressionV",&_compressionV);
comp_tree->SetBranchAddress("_compressionY",&_compressionY);
Long64_t nentries = compchain->GetEntries();
Long64_t nb = 0, nbytes = 0 ;
for (Long64_t i=0; i<nentries; i++) {
Long64_t entry = compchain->LoadTree(i);
if (entry <0 ) break;
nb = compchain->GetEntry(i); nbytes += nb;
cout << "entry = " << nb << endl;
cout << "compression = " << _compression << endl;
comp->Fill(_compression);
}
cout << "entries = " << nentries << endl;
}
And the output I get is a long repetition of this:
entry = 36
compression = 1.54768e-316
entry = 36
compression = 1.54768e-316
entry = 36
compression = 1.54768e-316
(and at the end, the correct number of entries).
What do I do to make it read out the correct entry?
Please help!
It looks you don't need to use the comp_tree pointer at all. The compchain pointer should be enough to access the data in the TTree because TChain is a TTree. Therefore, you should be able to "link" the variables to the chain/tree branches as:
compchain->SetBranchAddress("_compression",&_compression);
instead of
comp_tree->SetBranchAddress("_compression",&_compression);

cout error while using functions

I've encountered a problem while trying to create a code which converts decimal numbers to binary, using functions. At first I created the code using only main function and it worked fine, but decided to modify it to use function. I believe code is written right, however when I try to cout my answer I get a big number like 115120160758866453687091316369641637416.
This is the code
#include <iostream>
#include <math.h>
using namespace std;
int* unsigned_dec(int dec_M) { //function for converting absolute part of numbers
int bin[8] = { 0,0,0,0,0,0,0,0 };
int ind = 7;
int arr_ind = 0;
for (int base = (int)abs(dec_M); base > 0; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
ind--;
}
else {
bin[arr_ind] = 1;
ind--;
}
arr_ind++;
}
return bin;
}
int main() {// main function
int dec_N;
cin >> dec_N;
int* bin_main = unsigned_dec(dec_N); //we are not sure if we are assigning the returned value of function to array in correct
for (int i = 0; i <= 7; i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}
then I tried to change the cout code to
cout << bin_main[0] << bin_main[1] << bin_main[2] << bin_main[3] << bin_main[4] << bin_main[5] << bin_main[6] << bin_main[7] << endl;
And this worked fine.
Then I wrote the same 2nd variant of cout in other way
cout << bin_main[0];
cout << bin_main[1];
cout << bin_main[2];
cout << bin_main[3];
cout << bin_main[4];
cout << bin_main[5];
cout << bin_main[6];
cout << bin_main[7];
cout << endl;
and my code started to cout the same strange number. I think that all 3 ways of couts are almost the same (especially 2 and 3), but don't understand what makes it not to work.
int bin[8] = { 0,0,0,0,0,0,0,0 };
is allocated on stack. You should either allocate bin on heap
auto bin = std::unique_ptr<int, std::default_deleter<int[]>>(new int[8]);
or even better, use std::vector
you are returning pointer to local array of intbin[] in unsigned_dec. This array on stack of function unsigned_dec will get invalidated once another function from main gets called i.e cout operator .
As others have already mentioned: A function should never return a pointer to a local variable. Local variable is not valid when the function returns.
A better way is to use a vector and just make the function return the vector.
Something like:
#include <iostream>
#include <math.h>
using namespace std;
//function for converting absolute part of numbers
vector<int> unsigned_dec(int dec_M) {
vector<int> bin; // Create a vector
bin.resize(8, 0); // Fill it with 8 elements initialized to zero
int arr_ind = 0;
// Note: added check for arr_ind being valid
for (int base = (int)abs(dec_M); base > 0 && arr_ind < 8; base = base / 2) {
if (base % 2 == 0) {
bin[arr_ind] = 0;
}
else {
bin[arr_ind] = 1;
}
arr_ind++;
}
return bin; // Return the vector
}
int main() {
int dec_N;
cin >> dec_N;
vector<int> bin_main = unsigned_dec(dec_N);
for (int i = 0; i < bin_main.size(); i++) {
cout << bin_main[i];
}
cout << endl;
return 0;
}

Visual Studio C++ access violation when modifying a pointer passed into a function

I want to implement a simple function that gets a string as a char pointer and modifies the string in a function. The requested function must be void then I have to modify the primary string passed into my function. I got an access violation error and googled it but nothing helped.
My sample code is here:
#include "iostream"
using namespace std;
void FindCommonStr(char*& Common,int &A)
{
int i=0;
while(1)
{
if(Common[i]=='\0')
break;
i++;
}
cout<<"Number of Elements = "<<i<<endl;
for (int j=0 ; j<i-1;j++)
Common[j]='y';
A=2;
}
void main()
{
int A=0;
char* Common = new char;
Common = "Hello World!";
cout<<"Common0 = "<< Common<<endl;
cout<<"A0 = "<< A<<endl;
FindCommonStr(Common,A);
cout<<"Common1 = "<< Common<<endl;
cout<<"A1 = "<< A<<endl;
}
Actually the problem occured in this part of FindCommonStr funtion:
for (int j=0 ; j<i-1;j++)
Common[j]='y';
If I comment this part everything works but I cannot change the string values. I also tested the pointer to pointer solution by defining the function as:
FindCommonStr(char **Common,...
It doesn't help though and I got the violation error again.
Is it even possible to do such a thing?
When you do this:
Common = "Hello World!";
you are making the pointer Common point at a literal C-style string (and incidentally leaking the original char that you allocated via new previously). It is not valid to try to modify such a literal, so when you pass this to FindCommonStr and try to modify it you get an access violation.
You should avoid using C-style strings and use proper C++ std::string instead - this will save a lot of problems and is much more robust, as well as being more appropriate for C++ programming.
Fixed version of your code:
#include <iostream>
#include <string>
using namespace std;
static void FindCommonStr(string &Common, int &A)
{
int i = 0;
while (1)
{
if (Common[i] == '\0')
break;
i++;
}
cout << "Number of Elements = " << i << endl;
for (int j = 0; j < i - 1; j++)
Common[j] = 'y';
A = 2;
}
int main()
{
int A = 0;
string Common = "Hello World!";
cout << "Common0 = " << Common << endl;
cout << "A0 = " << A << endl;
FindCommonStr(Common, A);
cout << "Common1 = " << Common<<endl;
cout << "A1 = " << A << endl;
return 0;
}
Alternatively if this is a homework assignment where you are required to use C strings for some unfathomable reason then a fixed version using only char * strings might look like this:
#include <iostream>
using namespace std;
static void FindCommonStr(char *Common, int &A)
{
int i = 0;
while (1)
{
if (Common[i] == '\0')
break;
i++;
}
cout << "Number of Elements = " << i << endl;
for (int j = 0; j < i - 1; j++)
Common[j] = 'y';
A = 2;
}
int main()
{
int A = 0;
char Common[] = "Hello World!";
cout << "Common0 = " << Common << endl;
cout << "A0 = " << A << endl;
FindCommonStr(Common, A);
cout << "Common1 = " << Common<<endl;
cout << "A1 = " << A << endl;
return 0;
}
This part is conceptually wrong:
char* Common = new char;
// 'Common' is set to point to a piece of allocated memory
// (typically located in the heap)
Common = "Hello World!";
// 'Common' is set to point to a constant string
// (typically located in the code-section or in the data-section)
You are assigning variable Common twice, so obviously, the first assignment has no meaning.
It's like writing:
int i = 5;
i = 6;
On top of that, you "lose" the address of the allocated memory block, so you will not be able to release it at a later point in the execution of your program.
You seem to mixup char[] and string
When you write
char* Common = new char;
you allocate space on the heap for one character which Common is pointing to.
Then you write
Common = "Hello World!";
which sets the pointer Common to point to the string "Hello World" in read-only memory. The heap you allocated previously is now leaked.
There are basically two approaches:
Either you work with arrays of characters, in that case you write something like
char* Common = new char[strlen("Hello World!")+1];
strcpy(Common, "Hello World!");
Now common still points to the heap and the string has been copied there. The extra +1 byte is to hold the ending \0 string terminator.
You need to free the memory Common points to once you are done.
delete Common;
The other approach is to use the string template
std::string Common;
this allows you to assign a string, it capsules all the work with the heap array above.
Common = "Hello World!";
and there is no need to delete anything afterwards since std::string will do that for you.

Has anyone been able to use libsensors properly?

Long story short I am trying to write an application that can check cpu temperatures. Using the libsensors(3) man pages I've been able to at least get the libsensors_version number. As of now, here is my code:
#include <sensors/sensors.h>
#include "SensorData.h"
#include <string>
#include <sstream>
using namespace std;
SensorData::SensorData()
{
sensors_init(NULL);
}
SensorData::~SensorData()
{
sensors_cleanup();
}
string SensorData::GetVersion()
{
ostringstream Converter;
Converter<<"Version: "<<libsensors_version;
return Converter.str();
}
void SensorData::FetchTemp()
{
//sensors_get_value()
}
With the man pages I know that sensors_get_value expects
const sensors_chip_name *name
int subfeat_nr
double *value
to be passed to it. The problem is I have no idea what those are exactly. Just about every function in the documentation has this problem. They all expect vague things I don't know how to supply.
So here is the bulk of the question: Does anyone have any working examples of this library I could look at? Or at the very least does anyone know how to give these functions the values they need?
EDIT:
Since no one seems to know much about this library, does anyone know of a different way to get temperatures?
You can find out how to use the API by browsing the source code. The code for the sensors program isn't too complex to follow.
To get you started, here's a quick function that:
enumerates all the chips
enumerates all their features
prints the values of their readable subfeatures
You can just add it to your existing skeleton class as-is.
(This code is for demo purposes only, not tested thoroughly at all.)
void SensorData::FetchTemp()
{
sensors_chip_name const * cn;
int c = 0;
while ((cn = sensors_get_detected_chips(0, &c)) != 0) {
std::cout << "Chip: " << cn->prefix << "/" << cn->path << std::endl;
sensors_feature const *feat;
int f = 0;
while ((feat = sensors_get_features(cn, &f)) != 0) {
std::cout << f << ": " << feat->name << std::endl;
sensors_subfeature const *subf;
int s = 0;
while ((subf = sensors_get_all_subfeatures(cn, feat, &s)) != 0) {
std::cout << f << ":" << s << ":" << subf->name
<< "/" << subf->number << " = ";
double val;
if (subf->flags & SENSORS_MODE_R) {
int rc = sensors_get_value(cn, subf->number, &val);
if (rc < 0) {
std::cout << "err: " << rc;
} else {
std::cout << val;
}
}
std::cout << std::endl;
}
}
}
}
The Gnome panel Sensors applet works with libsensors (and other backends); the full sources are available from Sourceforge, here: http://sensors-applet.sourceforge.net/index.php?content=source
… in particular, the libsensors plug-in looks fairly legible… I believe this should be a usable gitweb link straight to that code: http://sensors-applet.git.sourceforge.net/git/gitweb.cgi?p=sensors-applet/sensors-applet;a=blob;f=plugins/libsensors/libsensors-plugin.c;h=960c19f4c36902dee4e20b690f2e3dfe6c715279;hb=HEAD
Your code should looks like this:
/* Read /etc/sensors.d to get the names or use code in above post */
std::string chip_name = "CHIP_NAME-*";
/* Here you get the path to the chip you want to read */
int rc;
sensors_chip_name name;
rc = sensors_parse_chip_name(chip_name.c_str(), &name);
/* Check rc != 0 */
/* Here you get the internal structure */
int nr = 0; //Here I silently assume you have only one chip to read
const sensors_chip_name* p_chip;
p_chip = sensors_get_detected_chips(&name, &nr);
/* Check p_chip != 0 */
/* Now you read the value - this you can repeat in some for/while cycle */
double val;
/* Replace the "1" with the feature you want to read */
rc = sensors_get_value(p_chip, 1, &val);
std::cout << "Now I can use sensors library " << val << std::endl;
Hope it helps despite the fact it is not copy/paste solution.
You can obtain the const sensors_chip_name* p_chip; from the code above post as well.
I believe the problem is in fact the const sensors_chip_name MUST be returned and filled by sensors library.