在Origin里調用DLL

来源:互联网 发布:换美元放在家里知乎 编辑:程序博客网 时间:2024/05/10 07:33

        Origin自帶的Origin C語言允許用戶通過編程來更高效地完成大批量的作圖和數據處理。應該看到,Origin C本身有著較大的局限:不支持自定義函數返回結構體類型的數據( "Origin C doesn't support external functions that return a struct type variable",http://ocwiki.originlab.com/index.php?title=OCGuide:Calling_GNU_Scientific_Library ),在循環結構里的執行速度很慢,等。

        因此,在必要的時候,我會自己寫個DLL供Origin C調用。如在這個帖子里:http://emuch.net/bbs/viewthread.php?tid=5432435,我給出的是Origin C寫的程序,現在稍加修改以便記錄執行耗時:

#include <Origin.h>int imp_one_line(){        string pstrOut;        okutil_FileDialog(&pstrOut, FALSE);               string pstrOut2;        struct tm *nowtime;        time_t aclock;        time(&aclock);        nowtime = localtime(&aclock);        pstrOut2 = pstrOut + "-" + (nowtime->tm_year + 1900) + "-" + (nowtime->tm_mon + 1) + "-" + (nowtime->tm_mday);        pstrOut2 = pstrOut2 + "-" + nowtime->tm_hour + "-" + nowtime->tm_min + "-" + nowtime->tm_sec + ".asc";               FILE *fp1,*fp2;        fp1 = fopen( pstrOut, "r" ) ;        fp2 = fopen(pstrOut2, "w" ) ;               fseek(fp1, 0L, SEEK_END ) ;        int f_end = ftell(fp1);        fseek(fp1, 0L, SEEK_SET ) ;               char *chrAll = (char*)calloc(f_end+1,sizeof(char) ) ;        if(!chrAll)                return -1;        fgets(chrAll,f_end,fp1 ) ;    // only ONE line of data        MessageBox(GetWindow(), "Just for the first line of data. Please click OK to continue.","Warning!" ) ;               Sleep(300 ) ;        LT_execute("type -a Converting...." ) ;               DWORD dw1 = GetTickCount();        int lchrAll = lstrlen(chrAll ) ;        for(int i=0;i<lchrAll;i++)                if(44==(int)chrAll [ i ])                        chrAll [ i ]=(char)10;               fputs(chrAll,fp2 ) ;        DWORD dw2 = GetTickCount();        Sleep(300 ) ;        LT_execute("type -a ....Done" ) ;               printf("%d ms\n",dw2-dw1);                fclose(fp1 ) ;        fclose(fp2 ) ;               Worksheet wks;        wks.Create("origin" ) ;        if(!wks)                return -2;        ASCIMP ai;        if( 0 == AscImpReadFileStruct(pstrOut2, &ai) )                if( 0 == wks.ImportASCII(pstrOut2, ai) )                        out_str("Import data successful." ) ;               return 0;}
執行結果顯示:

1> imp_one_line()=Converting........Done49407 msImport data successful.imp_one_line()=0

下面用調用DLL的方法來看看執行效果如果:

1. 編譯生成DLL

先新建項目,名稱為ocDLL:

應用程序設置見:

在解決方案資源管理器里可以看到已經有好個文件準備好了,把源文件里的文件類型全部由".cpp"改為".c",見下圖:

需要編輯的各文件的內容見下:

ocDLL.h

// ocDLL.h#ifdef OCDLL_EXPORTS#define OCDLL_API __declspec(dllexport)#else#define OCDLL_API __declspec(dllimport)#endifOCDLL_API int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, const char chSrc, const char chDst);

stdafx.h

// stdafx.h : 标准系统包含文件的包含文件,// 或是经常使用但不常更改的// 特定于项目的包含文件//#pragma once#include "targetver.h"#define WIN32_LEAN_AND_MEAN             //  从 Windows 头文件中排除极少使用的信息// Windows 头文件:#include <windows.h>// TODO: 在此处引用程序需要的其他头文件#include <stdio.h>#include <stdlib.h>#include <string.h>

ocDLL.c

#include "stdafx.h"#include "ocDLL.h"OCDLL_API int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, const char chSrc, const char chDst){long f_end;long f_now;long f_tmp;unsigned long i;unsigned long len_chAll;char * chAll;if( !(fpSrc && fpDst) )return -1;fseek( fpSrc, 0L, SEEK_END );f_end = ftell( fpSrc );fseek( fpSrc, 0L, SEEK_SET );chAll = (char*)calloc( f_end+3, sizeof(char) );if( !chAll )return -2;do{f_tmp = ftell( fpSrc );fgets( chAll, f_end+3, fpSrc );f_now = ftell( fpSrc );len_chAll = strlen(chAll);for( i = 0; i < len_chAll; i++ )if( chSrc == chAll[i] )chAll[i] = chDst;fputs( chAll, fpDst );chAll[0] = 0;}while(f_tmp < f_now );return 0;}

在解決方案配置為Release下,生成解決方案。如果生成成功,將在輸出窗口中看到大概如下的信息:

1>------ 已启动生成: 项目: ocDLL, 配置: Release Win32 ------1>  stdafx.c1>  dllmain.c1>  ocDLL.c1>     正在创建库 d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.lib 和对象 d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.exp1>  正在生成代码1>  已完成代码的生成1>  ocDLL.vcxproj -> d:\My Documents\Visual Studio 2010\Projects\ocDLL\Release\ocDLL.dll========== 生成: 成功 1 个,失败 0 个,最新 0 个,跳过 0 个 ==========
把生成的ocDLL.dll複製到Origin安裝目錄下的\OriginC\system\,再在該目錄里新建一個頭文件ocDLL.h:

#pragma dll(ocDLL,header)int o_delimiter_replace(FILE * fpSrc, FILE * fpDst, char chSrc, char chDst);
把本文第一個程序代碼改為:

#include <origin.h>#include <ocDLL.h>int imp_one_line(){        string pstrOut;        okutil_FileDialog(&pstrOut, FALSE);               string pstrOut2;        struct tm *nowtime;        time_t aclock;        time(&aclock);        nowtime = localtime(&aclock);        pstrOut2 = pstrOut + "-" + (nowtime->tm_year + 1900) + "-" + (nowtime->tm_mon + 1) + "-" + (nowtime->tm_mday);        pstrOut2 = pstrOut2 + "-" + nowtime->tm_hour + "-" + nowtime->tm_min + "-" + nowtime->tm_sec + ".asc";               FILE *fp1,*fp2;        fp1 = fopen( pstrOut, "r" ) ;        fp2 = fopen(pstrOut2, "w" ) ;               fseek(fp1, 0L, SEEK_END ) ;        int f_end = ftell(fp1);        fseek(fp1, 0L, SEEK_SET ) ;               char *chrAll = (char*)calloc(f_end+1,sizeof(char) ) ;        if(!chrAll)                return -1;        fgets(chrAll,f_end,fp1 ) ;    // only ONE line of data        MessageBox(GetWindow(), "Just for the first line of data. Please click OK to continue.","Warning!" ) ;               Sleep(300 ) ;        LT_execute("type -a Converting...." ) ;                DWORD dw1 = GetTickCount();        /*        int lchrAll = lstrlen(chrAll ) ;        for(int i=0;i<lchrAll;i++)                if(44==(int)chrAll [ i ])                        chrAll [ i ]=(char)10;               fputs(chrAll,fp2 ) ;        */        o_delimiter_replace(fp1,fp2,',','\n');        DWORD dw2 = GetTickCount();               Sleep(300 ) ;        LT_execute("type -a ....Done" ) ;               printf("%d ms\n",dw2-dw1);                fclose(fp1 ) ;        fclose(fp2 ) ;               Worksheet wks;        wks.Create("origin" ) ;        if(!wks)                return -2;        ASCIMP ai;        if( 0 == AscImpReadFileStruct(pstrOut2, &ai) )                if( 0 == wks.ImportASCII(pstrOut2, ai) )                        out_str("Import data successful." ) ;               return 0;}
需要注意的是,上面的代碼在處理返回值方面有待改進。
編譯,執行,得:

2> imp_one_line()=Converting........Done188 msImport data successful.imp_one_line()=0

儘管這樣子的比較不是很科學,但前後兩次所用時間差別很大,效率的提升相當明顯。

原创粉丝点击