Friday, June 29, 2012

How to Record and Play macro in Visual Studio

Macro comes in very handy if you have to repeat certain operation a lot of times.

Ctrl + Shift + R => Start
Ctrl + Shift + R => Stop
Ctrl + Shift + P => Play

I recently learned about them when i needed to put breakpoint on all the calls to function(SendEvent) and inspect the event id. At first i was manually putting the breakpoint but then i realised that the file was like 3K lines of code. So, instead what i did was search for "SendEvent" once and then after that pressing F3 will move to next occurrence of the searched string. Then move to the start of the file. Press Ctrl+Shift+R to start recording macro, press F3 to get to first matched string and then press F9 to put the breakpoint.  Press Ctrl+Shift+R to stop recording. Then keep pressing Ctrl+Shift+P till the end of the file.

Thursday, February 9, 2012

Yum cannot resolve $releasever - Fedora

Yesterday I was installing some packages with yum, but then later decided to cancel the install pressing Ctrl+C, after that i started noticing this issue. Whenever i tried to install anything yum spilled the following error.

Could not parse metalink http://mirrors.fedoraproject.org/metalink?repo=fedora-$releasever&arch=x86_64 error was
No repomd file

Yum was not able to resolve the value of $releasever variable. It turns out that it gets to know that value from the version of "fedora-release" package installed on the system.
After i figured that out, the solution was simple, just reinstall "fedora-release" for your current system. Since currently i am using fedora 15, I issued the following command

yum install fedora-release --releasever=15

Notice, you need to tell yum to use release version of the current fedora release using --releasever

Tuesday, November 1, 2011

What's the problem

No matter how much you think you know C/C++ there are things that you can always miss if you are not thorough. This small program is one of them. Can you tell me how many times "Java Rules" is printed ?
#include <stdio.h>

  int main()
  {
   int counter = -1;
   
   while( counter < sizeof(int))
   {
     printf("Java Rules!! \n");
     counter++;
   }
    
   return 0;
  }
The answer is none, because the fact is Java doesn't Rule :P
Alright alright, the reason is sizeof operator returns unsigned int :)

Sunday, October 16, 2011

Removing packages not supported by the Repository

Here's a small tip for rpm based systems (like fedora, centos etc) to remove all the obsolete packages that are not supported by the current repository.

  • List all packages not supported by the repository.
    $ package-cleanup --orphans


  • One can use xargs with the above command to remove them.
    $ package-cleanup --orphans | xargs yum remove -y
    

Monday, October 3, 2011

Calling C++ library function from C code

Recently one of my friend asked this question. I had done this in past but I had to struggle to do this again. So I am documenting this in case i need this again in future.

Let's first create a C++ shared library containing the functions we need.
Since, I am not good with names so I'll call it the "Person" class.


Person.h
#ifndef __PERSON_H__
#define __PERSON_H__

void globalMethod();

class Person
{
 public:
 void instanceMethod();
 static void classMethod();
};

#endif


Person.cpp
#include "Person.h"
#include <iostream>
using namespace std;

void globalMethod()
{
 cout<<"Global method"<<endl;
}

void Person::instanceMethod()
{
 cout<<"Instance method"<<endl;
}

void Person::classMethod()
{
 cout<<"Class method"<<endl;
}


After creating the source files we need to compile them into shared object.

$ g++ -fPIC -c Person.cpp
$ g++ -shared -o libPerson.so Person.o
$


At this point we have our C++ shared library.
A simple client in C++ for this library looks like this.

Client.cpp
#include "Person.h"

int main()
{
 Person p;
 p.instanceMethod();
 Person::classMethod();
 globalMethod();
}


We can compile and run this small program as such. We need to export LD_LIBRARY_PATH before running the binary, so that the loader can find the shared object.

$ g++ Client.cpp -o Client -L. -lPerson
$ export LD_LIBRARY_PATH=`pwd`:$LD_LIBRARY_PATH
$ ./Client
Instance method
Class method
Global method
$


Till here we know that everything works.
Now, lets call these methods from C code. But, as we know that C++ does name mangling we cannot directly call these methods from the C code. We first have to write some kind of wrapper over the existing library using C naming convention so that the names are not mangled.

Here is what the wrapper class looks like

Wrapper.cpp
#include "Person.h"

extern "C" void GlobalMethod()
{
 globalMethod();
}

extern "C" void InstanceMethod(Person *p)
{
 p->instanceMethod();
}

extern "C" void ClassMethod()
{
 Person::classMethod();
}

Note the InstanceMethod() takes a pointer to Person object. Why ??? Remember the *this* pointer in C++; since this method will be called from C code, we need to manually pass this variable.

This will be our wrapper shared library over the libPerson.so library. lets compile and create the library.

$ g++ -fPIC -c Wrapper.cpp
$ g++ -shared -o libWrapper.so Wrapper.o
$


Now, its time to write our Client in C; it looks like this

Client.c
struct Person
{
};

int main(){
 GlobalMethod();
 struct Person p;
 InstanceMethod(p);
 ClassMethod();
}

Pay attention that we have to create a Struct for the Person class. We need to link this binary against the wrapper library (libWrapper.so) and the actual library(libPerson.so), since the Wrapper depends upon it.


$ gcc Client.c -o C_Client -L. -lWrapper -lPerson
$ ./C_Client
Global method
Instance method
Class method
$


And, we're done !!

Any comments/suggestions are welcomed !!